CompareSG

Which poly teaches the course you want?

Pick a field and a course to see which of Singapore's 5 polytechnics list it, and what last year's students scored. 105 of 136 course titles are taught at only one poly. From MOE's 2027 JAE course list.

Full-time diploma courses for O-level students (JAE) only.

Find a course

9 fields, as MOE groups them
Course titles in that field, A to Z, with how many polys list each

Which polys offer Nursing?

Field: Health Sciences.

2 of 5 polytechnics list it

Nanyang Polytechnic and Ngee Ann Polytechnic list it. Republic Polytechnic, Singapore Polytechnic and Temasek Polytechnic do not.

Most course titles, 105 of 136, are taught at only one poly. This one is taught at 2.

  • Nanyang Polytechnic

    Code C97 · score type ELR2B2-C

    Scores of students posted in 2026
    7 to 28
  • Ngee Ann Polytechnic

    Code N69 · score type ELR2B2-C

    Scores of students posted in 2026
    6 to 28
  • Republic Polytechnic

    Does not list it.

  • Singapore Polytechnic

    Does not list it.

  • Temasek Polytechnic

    Does not list it.

A score is the net ELR2B2 aggregate: a smaller number is a better O-Level result. Each range runs from the highest-ranked student MOE posted to the course in 2026 to the last one. It shows who got in last year, not how good a course is, and 2027 can differ.

Other Health Sciences courses

No other course title shares a word with Nursing, so these are other Health Sciences courses. Tap one to look it up.

NYP Nanyang, NP Ngee Ann, RP Republic, SP Singapore, TP Temasek.

What does each poly teach, by field?

The number of courses each poly lists in each field. Darker means more. A dash means none. The field of your pick is outlined.

Courses each polytechnic lists in the 2027 JAE, by field
FieldNYPNPRPSPTPAll 5
Applied Sciences6666731
Built Environment1115210
Business & Management981251145
Engineering10858637
Health Sciences2251–10
Humanities141–39
Information & Digital Technologies5564626
Maritime Studies–1–2–3
Media & Design4662624
All fields3841423341195

Business & Management is the biggest field, with 45 of the 195 courses. Maritime Studies is the smallest, with 3. Some polys list nothing in a field: Temasek has no Health Sciences course and Singapore has no Humanities course.

What score did it take to get in last year?

Each dot is the score of the last student a poly posted to your pick in the 2026 JAE. A smaller score is a stronger O-Level result.

10152025NP, NYP 28
← Stronger scoreWeaker score →

Last year, the last student posted to Nursing scored 28 at Nanyang Polytechnic and 28 at Ngee Ann Polytechnic.

A score reflects how many people applied and how they did, not whether a course is good or which poly is better. Scores for 2027 can differ.

Fun finds

In every poly
Cybersecurity & Digital Forensics
Apart from the four common programmes, it is the only course title that all 5 polys list.
New for 2027
Two courses with no scores yet
Nanyang's Biopharmaceutical & Chemical Engineering (C23) was formed by merging two older courses. Republic's Defence & Security Management (R68) is also new.
The smallest field
Maritime Studies: 3 courses
Marine Engineering and Maritime Business at Singapore Polytechnic, and Offshore & Sustainable Engineering at Ngee Ann.

The short version

Polytechnic courses in Singapore for the 2027 JAE: the 5 polytechnics list 195 courses under 136 different titles, and 105 of those titles are taught at only one poly. 5 titles are taught at all five polys: the four common programmes and Cybersecurity & Digital Forensics. Scores are the 2026 JAE results printed in MOE's 2027 course list.

Pick a field and a course to see which polys list it, with the scores of the highest-ranked and the last student posted in 2026, the options listed inside it, and similar titles at any poly. Course titles are matched by exact name, so a course with a different name at another poly shows up under similar titles instead.

This lists what each poly offers and what last year's scores were. It is not a ranking and it says nothing about how good any poly or course is.

By Ben (opens in a new tab). Updated . Data: MOE, 2027 JAE course list.

Questions people ask

Which polytechnic offers nursing?

2 of the 5 polytechnics: Nanyang Polytechnic (C97) and Ngee Ann Polytechnic (N69). Applicants need a net ELR2B2 score of 28 or better for either. In 2026 the students posted to Nursing scored 7 to 28 at Nanyang and 6 to 28 at Ngee Ann. Republic, Singapore and Temasek do not list a course called Nursing.

How many polytechnic courses are there in Singapore?

For the 2027 JAE the 5 polytechnics list 195 courses under 136 different titles: Nanyang 38, Ngee Ann 41, Republic 42, Singapore 33, Temasek 41. 26 of the 195 are common programmes, broad entry courses that students choose a path from later.

Which polytechnic courses are taught at only one poly?

105 of the 136 course titles. The number of titles that only one poly lists: Nanyang 22, Ngee Ann 20, Republic 24, Singapore 15, Temasek 24. Pick a field and a course in the finder above to see each one.

Which courses do all five polytechnics offer?

Four common programmes (Business, Engineering, ICT and Science) and Cybersecurity & Digital Forensics. 3 more titles are listed by four polys: Aerospace Engineering, Applied AI & Analytics and Pharmaceutical Science.

Which polytechnic offers aerospace engineering?

Nanyang Polytechnic, Ngee Ann Polytechnic, Republic Polytechnic and Temasek Polytechnic list a course called Aerospace Engineering. Singapore Polytechnic does not use that title. It lists Aeronautical Engineering (S88) and Aerospace Electronics (S90). Check each course's own page to see how the content differs.

What were the polytechnic cut-off points for 2026?

Scores are not set in advance. MOE's list shows, for each course, the scores of the highest-ranked and the last student posted in the 2026 JAE. Of the 193 courses with 2026 scores, 25 had a last student posted at 10 or lower and 19 at 26 or higher. Scores for 2027 can differ.

What is a common programme?

A broad entry course, such as the Common ICT Programme, where students pick a path or a specialisation later. 26 of the 195 courses are common programmes, and the finder shows the options MOE lists inside each.

The numbers behind it

Course titles taught at two or more polys (31 of 136), 2027 JAE list
Course titleFieldPolysWhich polys
Common Business ProgrammeBusiness & Management5NYP, NP, RP, SP, TP
Common Engineering ProgrammeEngineering5NYP, NP, RP, SP, TP
Common ICT ProgrammeInformation & Digital Technologies5NYP, NP, RP, SP, TP
Common Science ProgrammeApplied Sciences5NYP, NP, RP, SP, TP
Cybersecurity & Digital ForensicsInformation & Digital Technologies5NYP, NP, RP, SP, TP
Aerospace EngineeringEngineering4NYP, NP, RP, TP
Applied AI & AnalyticsInformation & Digital Technologies4NYP, NP, RP, SP
Pharmaceutical ScienceApplied Sciences4NYP, NP, RP, TP
Applied ChemistryApplied Sciences3NYP, RP, SP
Banking & FinanceBusiness & Management3NYP, NP, SP
Biomedical EngineeringEngineering / Applied Sciences3NYP, NP, TP
Biomedical ScienceApplied Sciences3NP, RP, SP
Electrical & Electronic EngineeringEngineering3RP, SP, TP
Hospitality & Tourism ManagementBusiness & Management3NYP, RP, TP
Information TechnologyInformation & Digital Technologies3NP, RP, TP
AccountancyBusiness & Management2NP, SP
Accountancy & FinanceBusiness & Management2NYP, TP
Aerospace ElectronicsEngineering2SP, TP
ArchitectureBuilt Environment2NYP, SP
Aviation ManagementBusiness & Management2RP, TP
BusinessBusiness & Management2RP, TP
Computer EngineeringEngineering2SP, TP
DesignMedia & Design2NP, RP
Early Childhood Development & EducationHumanities2NP, TP
Electronic & Computer EngineeringEngineering2NYP, NP
Human Resource Management with PsychologyBusiness & Management2RP, SP
Mass CommunicationMedia & Design2NP, RP
Mechanical EngineeringEngineering2NP, SP
Mechatronics & RoboticsEngineering2NP, SP
NursingHealth Sciences2NYP, NP
OptometryHealth Sciences2NP, SP
Courses where the last student posted in 2026 had a score of 10 or lower (25 of 193)
CoursePolyFieldScores posted in 2026
Biomedical ScienceNPApplied Sciences3 to 7
Biomedical ScienceSPApplied Sciences3 to 7
Medical BiotechnologyTPApplied Sciences3 to 8
Applied AI & AnalyticsSPInformation & Digital Technologies5 to 8
Biomedical Science with AnalyticsNYPApplied Sciences6 to 8
Applied ChemistrySPApplied Sciences3 to 9
Banking & FinanceNPBusiness & Management3 to 9
Veterinary TechnologyTPApplied Sciences3 to 9
Common Science ProgrammeNPApplied Sciences4 to 9
Psychology StudiesTPHumanities4 to 9
Oral Health TherapyNYPHealth Sciences5 to 9
Pharmaceutical ScienceNPApplied Sciences5 to 9
Common Science ProgrammeSPApplied Sciences7 to 9
Business StudiesNPBusiness & Management3 to 10
Engineering ScienceNPEngineering3 to 10
Applied ChemistryNYPApplied Sciences4 to 10
Aerospace EngineeringTPEngineering5 to 10
Law & ManagementTPBusiness & Management5 to 10
Pharmaceutical ScienceTPApplied Sciences5 to 10
Psychology & Community DevelopmentNPHumanities5 to 10
Applied AI & AnalyticsNYPInformation & Digital Technologies7 to 10
Pharmaceutical ScienceNYPApplied Sciences7 to 10
Biomedical EngineeringNPEngineering8 to 10
Biomedical ScienceRPApplied Sciences8 to 10
Environmental & Marine ScienceRPApplied Sciences8 to 10
All 136 course titles and the polys that list them
Course titleFieldWhich polys
AccountancyBusiness & ManagementNP, SP
Accountancy & FinanceBusiness & ManagementNYP, TP
Advanced & Digital ManufacturingEngineeringNYP
Aeronautical EngineeringEngineeringSP
Aerospace ElectronicsEngineeringSP, TP
Aerospace EngineeringEngineeringNYP, NP, RP, TP
AI & Data EngineeringEngineeringNYP
AI RoboticsEngineeringNYP
Animation, Games & Visual EffectsMedia & DesignNYP
Applied AI & AnalyticsInformation & Digital TechnologiesNYP, NP, RP, SP
Applied Artificial IntelligenceInformation & Digital TechnologiesTP
Applied ChemistryApplied SciencesNYP, RP, SP
Architectural Technology & Building ServicesBuilt EnvironmentTP
ArchitectureBuilt EnvironmentNYP, SP
Arts & Entertainment Production ManagementMedia & DesignRP
Arts Business ManagementBusiness & ManagementNP
Aviation ManagementBusiness & ManagementRP, TP
Banking & FinanceBusiness & ManagementNYP, NP, SP
Big Data & AnalyticsInformation & Digital TechnologiesTP
Biological SciencesApplied SciencesRP
Biomedical EngineeringEngineering / Applied SciencesNYP, NP, TP
Biomedical ScienceApplied SciencesNP, RP, SP
Biomedical Science with AnalyticsApplied SciencesNYP
Biopharmaceutical & Chemical EngineeringApplied SciencesNYP
BusinessBusiness & ManagementRP, TP
Business & Financial TechnologyBusiness & ManagementNYP
Business AdministrationBusiness & ManagementSP
Business ManagementBusiness & ManagementNYP
Business Process & Engineering ManagementBusiness & ManagementRP
Business Process & SystemsBusiness & ManagementTP
Business StudiesBusiness & ManagementNP
Chemical & Biological EngineeringApplied SciencesSP
Chemical & Biomolecular EngineeringApplied SciencesNP
Chemical EngineeringApplied SciencesTP
Chinese Media & CommunicationMedia & DesignNP
Chinese StudiesHumanitiesNP
Civil EngineeringBuilt EnvironmentSP
Cloud EngineeringEngineeringNYP
Common Arts, Media & Design ProgrammeMedia & DesignRP
Common Business & Technology ProgrammeEngineeringNYP
Common Business ProgrammeBusiness & ManagementNYP, NP, RP, SP, TP
Common Design & Media ProgrammeMedia & DesignNYP
Common Design ProgrammeMedia & DesignTP
Common Engineering ProgrammeEngineeringNYP, NP, RP, SP, TP
Common ICT ProgrammeInformation & Digital TechnologiesNYP, NP, RP, SP, TP
Common Media ProgrammeMedia & DesignNP
Common Science ProgrammeApplied SciencesNYP, NP, RP, SP, TP
Common Sports & Health ProgrammeHealth SciencesRP
Communication & Motion DesignMedia & DesignNYP
Communication DesignMedia & DesignTP
Communications & Media ManagementBusiness & ManagementTP
Computer EngineeringEngineeringSP, TP
Computer ScienceInformation & Digital TechnologiesSP
ComputingInformation & Digital TechnologiesNYP
Computing with LawInformation & Digital TechnologiesNP
Consumer Insights & PsychologyBusiness & ManagementRP
Culinary Arts & ManagementBusiness & ManagementTP
Cybersecurity & Digital ForensicsInformation & Digital TechnologiesNYP, NP, RP, SP, TP
Defence & Security ManagementBusiness & ManagementRP
DesignMedia & DesignNP, RP
Digital Content CreationMedia & DesignRP
Digital Film & TelevisionMedia & DesignTP
Early Childhood Development & EducationHumanitiesNP, TP
Electrical & Electronic EngineeringEngineeringRP, SP, TP
Electrical EngineeringEngineeringNP
Electronic & Computer EngineeringEngineeringNYP, NP
EngineeringEngineeringRP
Engineering ScienceEngineeringNP
Engineering with BusinessEngineeringSP
Enterprise Cloud Computing & ManagementInformation & Digital TechnologiesRP
Environmental & Marine ScienceApplied SciencesRP
Environmental Science & SustainabilityApplied SciencesNP
Events & Project ManagementBusiness & ManagementRP
Experience DesignMedia & DesignNYP
Facilities ManagementBuilt EnvironmentSP
Fashion Management & DesignMedia & DesignTP
Film, Sound & VideoMedia & DesignNP
Financial TechnologyInformation & Digital TechnologiesRP
Food & Beverage BusinessBusiness & ManagementNYP
Food Science & NutritionApplied SciencesNYP
Food Science & TechnologyApplied SciencesSP
Food, Nutrition & Culinary ScienceApplied SciencesTP
Game Development & TechnologyInformation & Digital TechnologiesNYP
Hospitality & Tourism ManagementBusiness & ManagementNYP, RP, TP
Hotel & Leisure Facilities ManagementBuilt EnvironmentNP
Hotel & Leisure ManagementBusiness & ManagementRP
Human Resource Management with PsychologyBusiness & ManagementRP, SP
Immersive Media & Game DevelopmentInformation & Digital TechnologiesTP
Information TechnologyInformation & Digital TechnologiesNP, RP, TP
Integrated Community CareHealth SciencesRP
Integrated Events & Project ManagementBuilt EnvironmentSP
Integrated Facility ManagementBuilt EnvironmentTP
Interior Architecture & DesignMedia & DesignTP
Interior DesignMedia & DesignSP
International Trade & BusinessBusiness & ManagementNP
International Trade & LogisticsBusiness & ManagementTP
Landscape ArchitectureBuilt EnvironmentSP
Landscape Design & HorticultureApplied SciencesNP
Law & ManagementBusiness & ManagementTP
Marine EngineeringMaritime StudiesSP
Maritime BusinessMaritime StudiesSP
MarketingBusiness & ManagementTP
Mass CommunicationMedia & DesignNP, RP
Mechanical EngineeringEngineeringNP, SP
MechatronicsEngineeringTP
Mechatronics & RoboticsEngineeringNP, SP
Media & Communication ManagementBusiness & ManagementNYP
Media, Arts & DesignMedia & DesignSP
Medical BiotechnologyApplied SciencesTP
Mobility & Robotic SystemsEngineeringRP
NursingHealth SciencesNYP, NP
Offshore & Sustainable EngineeringMaritime StudiesNP
OptometryHealth SciencesNP, SP
Oral Health TherapyHealth SciencesNYP
Outdoor EducationHumanitiesRP
Perfumery & Cosmetic ScienceApplied SciencesSP
Pharmaceutical ScienceApplied SciencesNYP, NP, RP, TP
Product Experience & DesignMedia & DesignTP
Psychology & Community DevelopmentHumanitiesNP
Psychology StudiesHumanitiesTP
Real Estate BusinessBusiness & ManagementNP
Restaurant & Culinary ManagementBusiness & ManagementRP
Social Sciences in GerontologyHumanitiesTP
Social WorkHumanitiesNYP
Sonic ArtsMedia & DesignRP
Sport & Exercise ScienceHealth SciencesRP
Sport & Wellness ManagementBusiness & ManagementNYP
Sport CoachingHealth SciencesRP
Sports & HealthHealth SciencesRP
Stage & Live EventsMedia & DesignNP
Supply Chain ManagementBusiness & ManagementRP
Sustainability in Engineering with BusinessEngineeringNYP
Sustainable Built EnvironmentBuilt EnvironmentRP
Tamil Studies with Early EducationHumanitiesNP
Tourism & Resort ManagementBusiness & ManagementNP
Veterinary TechnologyApplied SciencesTP

The boring bit

Where the data comes from

MOE's course list for the 2027 Joint Admissions Exercise (JAE), a PDF, downloaded 10 Oct 2026. We read the five polytechnic sections: Nanyang, Ngee Ann, Republic, Singapore and Temasek. The junior college and ITE sections were left out. The scores are the "net ELR2B2 range for previous (2026) JAE", which MOE describes as the aggregate of the highest to the lowest ranked students admitted in 2026.

What is not claimed

  • Course titles are matched by exact name, ignoring capitals and treating "&" as "and". Courses that cover similar ground under different names, such as Aerospace Engineering and Aeronautical Engineering, are different titles here. Only the "similar titles" list tries to link them, by shared words in the title, with a few spelling pairs joined by hand (aerospace and aeronautical, accounting and accountancy, AI and artificial intelligence). It can miss courses and can link some that are not alike.
  • We count courses MOE lists with their own code. A course that students can reach as an option inside a broader course, such as a common programme, at a poly that does not list it separately is not counted as offered there. The options inside each course are shown as MOE prints them.
  • Only full-time diploma courses that O-level students enter through the JAE are here. Part-time and adult-learner courses, and other routes in, are not in MOE's list.
  • Scores are from the 2026 JAE only. MOE says they are a reference and that scores are not set in advance, so 2027 can differ.
  • 2 courses are new for 2027 and have no 2026 scores. They are counted in the 195 courses but not in the 193 that have scores.
  • The score type (the letter after ELR2B2) is MOE's. We show it as printed and do not explain which subjects it counts.
  • Fields are MOE's own headings. One title, Biomedical Engineering, sits in Engineering at some polys and Applied Sciences at others, so it is listed in both.
  • Fees, course content, class sizes and jobs after graduation are not in this list. This is not a ranking, and a poly with more courses, or a course with a lower score, is not better.

Coverage

All 5 polytechnic sections were read: 195 courses, Nanyang 38, Ngee Ann 41, Republic 42, Singapore 33, Temasek 41. 193 of the 195 have 2026 scores. They make 136 different titles.

Report an error. Corrections are logged publicly with a date.

How we did it
Text extractionPattern matchingName matchingFrequency counts
  1. Converted the PDF to text with pdftotext, keeping the column layout, so each course stays on its line.
  2. Cut out the five polytechnic sections. Each starts at its "Entry requirements of courses to" heading and ends where the next begins. The last one ends where the ITE section starts.
  3. Read each course line with a pattern: the title, the course code, the score type and the 2026 range (or a dash for a new course). Titles that wrap onto a second line, or sit above the code, have their own rules, and the footnote symbols are removed.
  4. Took the bullets under a course as its options, and the capitalised heading above it as its field. The pages are read one at a time, so options never run into the next course.
  5. Matched titles across polys by exact name and counted how many polys list each one.
  6. Checked the totals against each poly's own list: Nanyang 38, Ngee Ann 41, Republic 42, Singapore 33, Temasek 41.
Show the Python code
import collections, re

POLYS = [('NANYANG POLYTECHNIC', 'NYP'), ('NGEE ANN POLYTECHNIC', 'NP'), ('REPUBLIC POLYTECHNIC', 'RP'),
         ('SINGAPORE POLYTECHNIC', 'SP'), ('TEMASEK POLYTECHNIC', 'TP')]
# a course line: the title, the course code, the score type and the 2026 range ("-" for a new course)
COURSE = re.compile(r'^(?P<left>.*?\S)\s{2,}(?P<code>[A-Z]\d{2,3})\*?\s+(?P<type>ELR2B2-[A-D]|ELB4-[A-D]|ELR1B3-[A-D])\s+(?P<rng>\d+\s+to\s+\d+\*?|-)(?:\s{2,}|$)')
CODE_ONLY = re.compile(r'^\s+(?P<code>[A-Z]\d{2,3})\*?\s+(?P<type>ELR2B2-[A-D]|ELB4-[A-D]|ELR1B3-[A-D])\s+(?P<rng>\d+\s+to\s+\d+\*?|-)(?:\s{2,}|$)')
MARKS = '①-⑳-Ⓐ-ⓩ'          # footnote symbols the PDF draws as characters
HEADINGS = ('COURSES', 'NANYANG POLYTECHNIC', 'NGEE ANN POLYTECHNIC', 'REPUBLIC POLYTECHNIC', 'SINGAPORE POLYTECHNIC', 'TEMASEK POLYTECHNIC')


def parse(text):
    lines = text.split('\n')
    starts = {}
    for i, l in enumerate(lines):                      # each polytechnic section starts under "ENTRY REQUIREMENTS OF COURSES TO"
        if 'ENTRY REQUIREMENTS OF COURSES TO' in l:
            for j in range(i + 1, i + 4):
                for name, ab in POLYS:
                    if lines[j].strip() == name:
                        starts[ab] = j
    assert len(starts) == 5, starts
    ite = [i for i, l in enumerate(lines) if l.strip() == 'INSTITUTE OF TECHNICAL EDUCATION']
    order = sorted(starts.items(), key=lambda kv: kv[1])
    bounds = {}
    for k, (ab, s) in enumerate(order):                # a section ends where the next begins; the last one where the ITE section starts
        after = [i for i in ite if i > s]
        e = order[k + 1][1] if k + 1 < len(order) else (min(after) if after else len(lines))
        bounds[ab] = (s, e)
    rows = []
    for ab, (s, e) in bounds.items():
        field, cur = '', None
        for i in range(s, e):
            l = lines[i]
            if '\f' in l:
                cur = None
            l = l.replace('\f', '')
            st = l.strip()
            mo = CODE_ONLY.match(l)
            if mo and not COURSE.match(l):             # the title sits on the line above the code
                prev = lines[i - 1]
                title = re.split(r'\s{3,}', prev.strip())[0]
                cur = dict(poly=ab, field=field, code=mo.group('code'), title=title, type=mo.group('type'), rng=mo.group('rng'),
                           notes=[], indent=len(prev) - len(prev.lstrip()))
                rows.append(cur)
                continue
            m = COURSE.match(l)
            if m:
                indent = len(l) - len(l.lstrip())
                cur = dict(poly=ab, field=field, code=m.group('code'), title=m.group('left').strip(), type=m.group('type'), rng=m.group('rng'),
                           notes=[], indent=indent)
                rows.append(cur)
                j = i + 1                              # a long title wraps onto the next line
                while j < e and lines[j].strip() and not COURSE.match(lines[j]):
                    part = lines[j][indent:indent + 42].rstrip().strip()
                    if not part or lines[j][:indent].strip():
                        break
                    if re.match(r'^(At the end|\(|•|Specialisations|This is|The first|Course Title|These|Note|Common|\*|Subject|\d)', part) or part.startswith('Notes'):
                        break
                    if len(part) <= 34 and len(lines[j]) - len(lines[j].lstrip()) == indent and not part.endswith(':'):
                        cur['title'] += ' ' + part
                        j += 1
                    else:
                        break
                continue
            if st and re.fullmatch(r"[A-Z&,\-' /\(\)]{6,}", st) and st not in HEADINGS and not st.startswith('ELR') \
                    and 'ENTRY REQUIREMENTS' not in st and 'COURSES TO' not in st and len(l) - len(l.lstrip()) < 12:
                field, cur = st, None                  # a capitalised heading is a field
                continue
            if cur is not None:                        # bullets under a course are the options inside it
                left = l[cur['indent']:cur['indent'] + 42].strip() if len(l) > cur['indent'] else ''
                lind = len(l) - len(l.lstrip())
                if left.startswith('•'):
                    cur['notes'].append(left.lstrip('• ').strip())
                    cur['open'] = True
                elif left and cur.get('open') and cur['notes'] and cur['indent'] < lind < cur['indent'] + 40 \
                        and not left.startswith(('Specialisations', 'Dip', 'The first', 'At the end')):
                    cur['notes'][-1] += ' ' + left
                else:
                    cur['open'] = False
    out = []
    for r in rows:
        low = high = None
        if r['rng'] != '-':
            low, high = [int(x) for x in re.findall(r'\d+', r['rng'])[:2]]
        title = re.sub(r'\s+', ' ', re.sub('[' + MARKS + ']', '', r['title'])).strip()
        out.append(dict(poly=r['poly'], code=r['code'], title=title, field=r['field'].title(), aggregate=r['type'], low=low, high=high,
                        common=title.lower().startswith('common '), new=r['rng'] == '-',
                        options=[re.sub(r'\s+', ' ', re.sub('[' + MARKS + ']', '', n)).strip() for n in r['notes']]))
    return out


def same_title(t):
    """Two courses have the same title when the names match, ignoring capitals and treating "&" as "and"."""
    return re.sub(r'\s+', ' ', t.lower().replace('&', 'and')).strip()


def count_titles(rows):
    polys = collections.defaultdict(set)
    for r in rows:
        polys[same_title(r['title'])].add(r['poly'])
    return len(polys), sorted(collections.Counter(len(v) for v in polys.values()).items())

# usage:  text = open("jae2027.txt", encoding="utf-8").read()   (from: pdftotext -layout jae2027.pdf jae2027.txt)
#         rows = parse(text); print(len(rows), "courses"); print(count_titles(rows))   # 195 courses; (136, [(1, 105), (2, 16), (3, 7), (4, 3), (5, 5)])

No machine learning was needed. The question was "who lists what", which reading the list and counting answers directly.

Sources: MOE 2027 JAE course list (opens in a new tab) (PDF), downloaded 10 Oct 2026. More on MOE's JAE page (opens in a new tab).