All SolutionsAll Solutions
🏂
Winter Olympics
Week 6, 2026
python - CSV | loops | BMC | Python Solutions
# (%%) means that I used Jupyter to run code in segments ;)
# %%
import csv
data = []
with open("winter-olympics.csv", newline='') as file:
reader = csv.reader(file)
for row in reader: data.append(row)
# %%
country_idx = {}
ans = []
# indexes
country_name = 0
total_medals = 1
total_entries = 2
win_rate = 3
gold_medal = 4
silver_medal = 5
bronze_medal = 6
total_men = 7
total_women = 8
men_medal_percentage = 9
total_win_men = 10
total_win_women = 11
curridx = 0
for i in range(1, len(data)):
country = data[i][4]
if "-" in country:
country = country[:country.index("-")]
if country not in country_idx:
country_idx.update({country:curridx})
ans.append([country, 0, 0, 0.00, 0, 0, 0, 0, 0, 0.00, 0, 0])
curridx += 1
cidx = country_idx[country]
ans[cidx][total_entries] += 1
match data[i][2]:
case 'M' : ans[cidx][total_men] +=1
case 'F' : ans[cidx][total_women] += 1
if data[i][12] != "":
ans[cidx][total_medals] += 1
match data[i][12]:
case "Gold" : ans[cidx][gold_medal] += 1
case "Silver" : ans[cidx][silver_medal] += 1
case "Bronze" : ans[cidx][bronze_medal] += 1
match data[i][2]:
case 'M' : ans[cidx][total_win_men] +=1
case 'F' : ans[cidx][total_win_women] += 1
# %%
# --- finally getting the answer ---
ans.sort(key=lambda x: (-x[total_medals], x[total_entries], x[country_name]))
for line in ans:
fcountry_name = line[country_name ]
ftotal_medals = line[total_medals ]
ftotal_entries = line[total_entries ]
fwin_rate = line[win_rate ]
fgold_medal = line[gold_medal ]
fsilver_medal = line[silver_medal ]
fbronze_medal = line[bronze_medal ]
ftotal_men = line[total_men ]
ftotal_women = line[total_women ]
fmen_medal_percentage = line[men_medal_percentage]
ftotal_win_men = line[total_win_men ]
ftotal_win_women = line[total_win_women ]
fwin_rate = ftotal_medals/ftotal_entries*100
fwin_rate = f"{fwin_rate:.2f}"
if ftotal_medals == 0:
msg = f"{fcountry_name} has won {ftotal_medals} medals from {ftotal_entries} entries - a win rate of {fwin_rate}%. Their medal breakdown is {fgold_medal} golds, {fsilver_medal} silvers and {fbronze_medal} bronzes. {ftotal_win_men} men and {ftotal_win_women} women have won medals."
else:
fmen_medal_percentage = ftotal_win_men/ftotal_medals*100
fmen_medal_percentage = f"{fmen_medal_percentage:.2f}"
msg = f"{fcountry_name} has won {ftotal_medals} medals from {ftotal_entries} entries - a win rate of {fwin_rate}%. Their medal breakdown is {fgold_medal} golds, {fsilver_medal} silvers and {fbronze_medal} bronzes. {ftotal_win_men} men and {ftotal_win_women} women have won medals - meaning {fmen_medal_percentage}% of medals have been won by men."
print(msg)
# %%
Collect, Sort, Format, Print | greenya | Odin Solutions
package main
import "core:encoding/csv"
import "core:fmt"
import "core:slice"
import "core:strings"
input_bytes := #load("winter-olympics.csv")
Country_Stat :: struct {
name : string,
total_entries : int,
total_medals : int,
total_medal : [Medal] int,
total_medal_sex : [Sex] int,
}
Sex :: enum { male, female }
Medal :: enum { bronze, silver, gold }
main :: proc () {
countries := countries_stats(string(input_bytes))
slice.sort_by(countries, less=proc (a, b: Country_Stat) -> bool {
switch {
case a.total_medals != b.total_medals:
return a.total_medals > b.total_medals
case a.total_entries != b.total_entries:
return a.total_entries < b.total_entries
case:
return 0 > strings.compare(a.name, b.name)
}
})
for c in countries {
male_medal_percentage_str := c.total_medals > 0\
? fmt.tprintf(
" - meaning %.2f%% of medals have been won by men",
f32(c.total_medal_sex[.male]*100) / f32(c.total_medals),
) : ""
fmt.printfln(
"%s has won %i medals from %i entries - a win rate of %.2f%%. " +
"Their medal breakdown is %i golds, %i silvers and %i bronzes. " +
"%i men and %i women have won medals%s.",
c.name,
c.total_medals,
c.total_entries,
f32(c.total_medals*100) / f32(c.total_entries),
c.total_medal[.gold],
c.total_medal[.silver],
c.total_medal[.bronze],
c.total_medal_sex[.male],
c.total_medal_sex[.female],
male_medal_percentage_str,
)
}
}
countries_stats :: proc (csv_text: string, allocator := context.allocator) -> [] Country_Stat {
reader := csv.Reader { reuse_record_buffer=true, reuse_record=true }
csv.reader_init_with_string(&reader, csv_text, context.temp_allocator)
countries := make(map [string] Country_Stat, context.temp_allocator)
for rec, idx, err in csv.iterator_next(&reader) {
// fmt.println(err, idx, rec)
assert(err == nil)
if idx == 0 do continue // skip row with column names
rec_sex := rec[2]
rec_name := rec[4]
rec_medal := rec[12]
dash_idx := strings.last_index(rec_name, "-")
if dash_idx >= 0 {
rec_name = rec_name[:dash_idx]
}
if rec_name not_in countries {
c := Country_Stat { name=strings.clone(rec_name, allocator) }
countries[c.name] = c
}
c := &countries[rec_name]
c.total_entries += 1
if rec_medal != "" {
c.total_medals += 1
medal := parse_medal(rec_medal)
c.total_medal[medal] += 1
sex := parse_sex(rec_sex)
c.total_medal_sex[sex] += 1
}
}
result, _ := slice.map_values(countries, allocator=allocator)
return result
}
parse_sex :: proc (s: string) -> Sex {
switch s {
case "M": return .male
case "F": return .female
case : fmt.panicf("Unexpected sex: %s", s)
}
}
parse_medal :: proc (s: string) -> Medal {
switch s {
case "Bronze" : return .bronze
case "Silver" : return .silver
case "Gold" : return .gold
case : fmt.panicf("Unexpected medal: %s", s)
}
}