1. Porovnání (Binomické koeficienty)
Porovnání jednotlivých řešení po tvrdém deadline prvního rozcvičkového a seznamovacího úkolu.
using CSV, DataFrames"""
record_rank!(data_frame, column)
Pomocná hodnotící funkce přidělující body do sloupce `score` tabulky
`data_frame` podle pořadí ve sloupci `column` (seřazeném).
"""
function record_rank!(data_frame::DataFrame, column::Symbol)
rank = 1
value = first(data_frame[!, column])
for row in eachrow(data_frame)
if ismissing(row[column])
row[:score] += 42
continue
elseif ismissing(value)
value = row[column]
elseif row[column] != value
value = row[column]
rank += 1
end
row[:score] += rank
end
end;Načtení dat, smazání username a přidání "skórovacího" sloupce a výpis základních statistik datasetu.
df = CSV.read("benchmark01.csv", DataFrame)
df[!, "score"] .= 0
select!(df, Not(:username))
describe(df)| Row | variable | mean | min | median | max | nmissing | eltype |
|---|---|---|---|---|---|---|---|
| Symbol | Union… | Any | Union… | Any | Int64 | Type | |
| 1 | nick | Aeloria of the Seven Sigils | kalvotom | 0 | String | ||
| 2 | code | 30.8367 | 1 | 29.0 | 49 | 4 | Union{Missing, Int64} |
| 3 | comment | 18.5306 | 0 | 16.0 | 77 | 4 | Union{Missing, Int64} |
| 4 | correctness | 0.811321 | false | 1.0 | true | 0 | Bool |
| 5 | test_int64_t | 239.049 | 1.994 | 2.215 | 6734.86 | 9 | Union{Missing, Float64} |
| 6 | test_int64_m | 192.182 | 0 | 0.0 | 7768 | 9 | Union{Missing, Int64} |
| 7 | test_int64_c | 0.830189 | false | 1.0 | true | 0 | Bool |
| 8 | test_bigint_t | 52041.1 | 1172.2 | 20759.0 | 1.25691e6 | 6 | Union{Missing, Float64} |
| 9 | test_bigint_m | 67225.0 | 768 | 27344.0 | 1682056 | 6 | Union{Missing, Int64} |
| 10 | test_bigint_c | 0.886792 | false | 1.0 | true | 0 | Bool |
| 11 | test_cfloat64_t | 1883.52 | 2.024 | 162.753 | 42139.0 | 4 | Union{Missing, Float64} |
| 12 | test_cfloat64_m | 1784.33 | 0 | 0.0 | 49368 | 4 | Union{Missing, Int64} |
| 13 | test_cfloat64_c | 0.924528 | false | 1.0 | true | 0 | Bool |
| 14 | score | 0.0 | 0 | 0.0 | 0 | 0 | Int64 |
Do měření započítávám pouze odevzdání, která počítají správné výsledky v typech Int64, BigInt, Float64, Complex{Float64} a Complex{BigFloat}.
Dále mezi hodnocené zařazuji i své odevzdání (nick kalvotom), kód vygenerovaný pomocí ChatGPT (nick chatgpt) a vnitřní implementaci (zobecněného) binomického koeficientu dostupného v Julia ve formě binomial methody (nick julia, příslušný main.jl tak obsahuje pouze binom = binomial).
df = df[df[:, :correctness], :];Parametry kódu
Počet řádek kódu. Čím méně, tím lépe, což ale vždy neplatí, že. Měření pomocí nástroje cloc.
sort!(df, :code)
record_rank!(df, :code)
show(df[!,[:nick, :code, :score]], allrows=true)43×3 DataFrame Row │ nick code score │ String Int64? Int64 ─────┼────────────────────────────────────────────────── 1 │ julia 1 1 2 │ Ilyrien Dawnpetal 17 2 3 │ Vyrion the Eternal 21 3 4 │ Velindra the Azure 22 4 5 │ Orren Emberforge 22 4 6 │ Dravok the Gloomed 23 5 7 │ Maranelle Frostpetal 23 5 8 │ Talvorn Runebreaker 24 6 9 │ Orlien Silverchant 25 7 10 │ Cyralis Moonbinder 25 7 11 │ kalvotom 26 8 12 │ Bramor the Tempest 26 8 13 │ Caelwyn of the Crystal Spire 26 8 14 │ Erenwyn the Whispering 26 8 15 │ Sareth the Verdant 26 8 16 │ Aeloria of the Seven Sigils 26 8 17 │ Zytherin the Forgotten 26 8 18 │ Lunara Dreambinder 27 9 19 │ Kerron the Unseen 27 9 20 │ Zerathorn the Pale 28 10 21 │ Maerilith Stormweaver 28 10 22 │ Dromek the Bound 28 10 23 │ Gorvath Ironchant 28 10 24 │ Eldaric Runehand 29 11 25 │ Rhovar Mistborn 29 11 26 │ chatgpt 30 12 27 │ Thamior Embercloak 30 12 28 │ Morvain Duskwalker 30 12 29 │ Velmaris Lightbinder 30 12 30 │ Galdur the Wise 31 13 31 │ Sylthara the Veiled 31 13 32 │ Xandor the Arcane 32 14 33 │ Korthen Deepflame 33 15 34 │ Vessryn Bloodsong 33 15 35 │ Nimriel the Golden 35 16 36 │ Faelora Nightbloom 37 17 37 │ Yseline Frostwhisper 39 18 38 │ Valtheris of the Amber Flame 39 18 39 │ Selvethra of the Whispering Woods 40 19 40 │ Talmek the Shattered 43 20 41 │ Mirelda Starbloom 44 21 42 │ Althira Starweaver 47 22 43 │ Korvath the Obsidian 49 23
Počet řádek komentářů (včetně docstringů). Zde naopak čím více, tím lépe.
sort!(df, :comment, rev=true)
record_rank!(df, :comment)
show(df[!,[:nick, :comment, :score]], allrows=true)43×3 DataFrame Row │ nick comment score │ String Int64? Int64 ─────┼─────────────────────────────────────────────────── 1 │ Althira Starweaver 42 23 2 │ Eldaric Runehand 41 13 3 │ Morvain Duskwalker 40 15 4 │ Aeloria of the Seven Sigils 31 12 5 │ Lunara Dreambinder 29 14 6 │ Orren Emberforge 28 10 7 │ Dromek the Bound 28 16 8 │ Sylthara the Veiled 28 19 9 │ Velmaris Lightbinder 24 19 10 │ Galdur the Wise 24 20 11 │ Maerilith Stormweaver 23 18 12 │ chatgpt 22 21 13 │ Thamior Embercloak 22 21 14 │ Maranelle Frostpetal 21 15 15 │ Talvorn Runebreaker 21 16 16 │ Orlien Silverchant 20 18 17 │ Rhovar Mistborn 20 22 18 │ Mirelda Starbloom 20 32 19 │ Caelwyn of the Crystal Spire 18 20 20 │ Erenwyn the Whispering 17 21 21 │ Vessryn Bloodsong 17 28 22 │ Dravok the Gloomed 16 19 23 │ Faelora Nightbloom 16 31 24 │ Bramor the Tempest 15 23 25 │ Nimriel the Golden 15 31 26 │ kalvotom 14 24 27 │ Zytherin the Forgotten 14 24 28 │ Vyrion the Eternal 12 20 29 │ Talmek the Shattered 12 37 30 │ Velindra the Azure 11 22 31 │ Zerathorn the Pale 11 28 32 │ Cyralis Moonbinder 10 26 33 │ Gorvath Ironchant 10 29 34 │ Korthen Deepflame 10 34 35 │ Yseline Frostwhisper 10 37 36 │ Xandor the Arcane 9 34 37 │ Ilyrien Dawnpetal 7 23 38 │ Kerron the Unseen 6 31 39 │ Valtheris of the Amber Flame 6 40 40 │ Korvath the Obsidian 2 46 41 │ Selvethra of the Whispering Woods 1 43 42 │ julia 0 26 43 │ Sareth the Verdant 0 33
Int64
Test s oběma argumenty typy Int64. V testu počítáme vždy několik (všichni stejný) binomických koeficentů pro několik různých k. Zde je výsledek měření doby běhu, seřazeno relativně k nejrychlejšímu. Vzhledem k jednoduchosti metody odhaduji, že u prvních cca dvou desítek míst jde spíše o chybu měření. Poslední sloupec pro jistotu (znovu) zaznamenává správnost výsledků u tohoto konkrétního experimentu.
sort!(df, :test_int64_t)
df[!, :test_int64_t] /= df[1, :test_int64_t]
record_rank!(df, :test_int64_t)
show(df[!,[:nick, :test_int64_t, :score, :test_int64_c]], allrows=true)43×4 DataFrame Row │ nick test_int64_t score test_int64_c │ String Float64 Int64 Bool ─────┼────────────────────────────────────────────────────────────────────── 1 │ Althira Starweaver 1.0 24 true 2 │ Velmaris Lightbinder 1.0 20 true 3 │ Maerilith Stormweaver 1.0 19 true 4 │ Dravok the Gloomed 1.0 20 true 5 │ kalvotom 1.0 25 true 6 │ Zerathorn the Pale 1.0 29 true 7 │ Cyralis Moonbinder 1.0 27 true 8 │ Korthen Deepflame 1.0 35 true 9 │ Korvath the Obsidian 1.0 47 true 10 │ Sareth the Verdant 1.0 34 true 11 │ Caelwyn of the Crystal Spire 1.00451 22 true 12 │ Aeloria of the Seven Sigils 1.01003 15 true 13 │ Vessryn Bloodsong 1.01454 32 true 14 │ Erenwyn the Whispering 1.01505 26 true 15 │ Dromek the Bound 1.02006 22 true 16 │ Zytherin the Forgotten 1.02006 30 true 17 │ Valtheris of the Amber Flame 1.02006 46 true 18 │ Eldaric Runehand 1.11033 20 true 19 │ Rhovar Mistborn 1.11033 29 true 20 │ Velindra the Azure 1.11033 29 true 21 │ Xandor the Arcane 1.11033 41 true 22 │ Orlien Silverchant 1.11083 26 true 23 │ Gorvath Ironchant 1.11083 37 true 24 │ Kerron the Unseen 1.11535 40 true 25 │ Faelora Nightbloom 1.12588 41 true 26 │ Lunara Dreambinder 1.13039 25 true 27 │ Ilyrien Dawnpetal 1.13541 35 true 28 │ chatgpt 1.32648 34 true 29 │ Orren Emberforge 1.33149 24 true 30 │ Maranelle Frostpetal 1.35155 30 true 31 │ Nimriel the Golden 1.46189 47 true 32 │ Sylthara the Veiled 1.68806 36 true 33 │ Talvorn Runebreaker 1.7984 34 true 34 │ Morvain Duskwalker 35.558 34 true 35 │ Galdur the Wise 43.9592 40 true 36 │ Mirelda Starbloom 63.7476 53 true 37 │ Vyrion the Eternal 91.8384 42 true 38 │ julia 106.927 49 true 39 │ Selvethra of the Whispering Woods 120.12 67 true 40 │ Talmek the Shattered 359.975 62 true 41 │ Bramor the Tempest 456.396 49 true 42 │ Thamior Embercloak 469.256 48 true 43 │ Yseline Frostwhisper 3377.56 65 true
A pak paměť ve stejném experimentu, čím méně, tím lépe.
sort!(df, :test_int64_m)
record_rank!(df, :test_int64_m)
show(df[!, [:nick, :test_int64_m, :score]], allrows=true)43×3 DataFrame Row │ nick test_int64_m score │ String Int64? Int64 ─────┼──────────────────────────────────────────────────────── 1 │ Althira Starweaver 0 25 2 │ Velmaris Lightbinder 0 21 3 │ Maerilith Stormweaver 0 20 4 │ Dravok the Gloomed 0 21 5 │ kalvotom 0 26 6 │ Zerathorn the Pale 0 30 7 │ Cyralis Moonbinder 0 28 8 │ Korthen Deepflame 0 36 9 │ Korvath the Obsidian 0 48 10 │ Sareth the Verdant 0 35 11 │ Caelwyn of the Crystal Spire 0 23 12 │ Aeloria of the Seven Sigils 0 16 13 │ Vessryn Bloodsong 0 33 14 │ Erenwyn the Whispering 0 27 15 │ Dromek the Bound 0 23 16 │ Zytherin the Forgotten 0 31 17 │ Valtheris of the Amber Flame 0 47 18 │ Eldaric Runehand 0 21 19 │ Rhovar Mistborn 0 30 20 │ Velindra the Azure 0 30 21 │ Xandor the Arcane 0 42 22 │ Orlien Silverchant 0 27 23 │ Gorvath Ironchant 0 38 24 │ Kerron the Unseen 0 41 25 │ Faelora Nightbloom 0 42 26 │ Lunara Dreambinder 0 26 27 │ Ilyrien Dawnpetal 0 36 28 │ chatgpt 0 35 29 │ Orren Emberforge 0 25 30 │ Maranelle Frostpetal 0 31 31 │ Nimriel the Golden 0 48 32 │ Sylthara the Veiled 0 37 33 │ Talvorn Runebreaker 0 35 34 │ Morvain Duskwalker 0 35 35 │ Galdur the Wise 0 41 36 │ Mirelda Starbloom 0 54 37 │ Vyrion the Eternal 0 43 38 │ Selvethra of the Whispering Woods 0 68 39 │ Talmek the Shattered 0 63 40 │ Thamior Embercloak 0 49 41 │ julia 80 51 42 │ Bramor the Tempest 608 52 43 │ Yseline Frostwhisper 7768 69
BigInt
Stejný experiment s BigInt argumenty.
sort!(df, :test_bigint_t)
df[!, :test_bigint_t] /= df[1, :test_bigint_t]
record_rank!(df, :test_bigint_t)
show(df[!,[:nick, :test_bigint_t, :score, :test_bigint_c]], allrows=true)43×4 DataFrame Row │ nick test_bigint_t score test_bigint_c │ String Float64 Int64 Bool ─────┼──────────────────────────────────────────────────────────────────────── 1 │ julia 1.0 52 true 2 │ Maerilith Stormweaver 10.1369 22 true 3 │ kalvotom 10.4511 29 true 4 │ Vyrion the Eternal 11.3846 47 true 5 │ Dravok the Gloomed 13.1081 26 true 6 │ chatgpt 14.4446 41 true 7 │ Sareth the Verdant 14.936 42 true 8 │ Rhovar Mistborn 14.9488 38 true 9 │ Orlien Silverchant 15.6236 36 true 10 │ Vessryn Bloodsong 15.7345 43 true 11 │ Faelora Nightbloom 15.7866 53 true 12 │ Talmek the Shattered 16.5769 75 true 13 │ Zytherin the Forgotten 17.3503 44 true 14 │ Xandor the Arcane 17.4441 56 true 15 │ Valtheris of the Amber Flame 17.4612 62 true 16 │ Mirelda Starbloom 17.4962 70 true 17 │ Sylthara the Veiled 17.5038 54 true 18 │ Kerron the Unseen 17.5636 59 true 19 │ Maranelle Frostpetal 17.6237 50 true 20 │ Aeloria of the Seven Sigils 17.6412 36 true 21 │ Orren Emberforge 17.7094 46 true 22 │ Zerathorn the Pale 17.8297 52 true 23 │ Caelwyn of the Crystal Spire 17.8336 46 true 24 │ Eldaric Runehand 17.8971 45 true 25 │ Velindra the Azure 17.898 55 true 26 │ Erenwyn the Whispering 18.0003 53 true 27 │ Lunara Dreambinder 18.2354 53 true 28 │ Morvain Duskwalker 18.3416 63 true 29 │ Velmaris Lightbinder 18.4358 50 true 30 │ Althira Starweaver 18.8466 55 true 31 │ Nimriel the Golden 18.966 79 true 32 │ Gorvath Ironchant 19.2646 70 true 33 │ Cyralis Moonbinder 20.128 61 true 34 │ Galdur the Wise 20.1753 75 true 35 │ Dromek the Bound 20.3336 58 true 36 │ Yseline Frostwhisper 25.807 105 true 37 │ Selvethra of the Whispering Woods 29.4182 105 true 38 │ Thamior Embercloak 35.7136 87 true 39 │ Talvorn Runebreaker 46.2686 74 true 40 │ Korthen Deepflame 56.1278 76 true 41 │ Korvath the Obsidian 56.6328 89 true 42 │ Ilyrien Dawnpetal 118.794 78 true 43 │ Bramor the Tempest 1072.26 95 true
A pak paměť, čím méně, tím lépe.
sort!(df, :test_bigint_m)
record_rank!(df, :test_bigint_m)
show(df[!, [:nick, :test_bigint_m, :score]], allrows=true)43×3 DataFrame Row │ nick test_bigint_m score │ String Int64? Int64 ─────┼───────────────────────────────────────────────────────── 1 │ julia 768 53 2 │ kalvotom 14632 31 3 │ Vyrion the Eternal 17328 50 4 │ Dravok the Gloomed 18496 30 5 │ Maerilith Stormweaver 19680 27 6 │ Vessryn Bloodsong 23528 49 7 │ chatgpt 23768 48 8 │ Aeloria of the Seven Sigils 26400 44 9 │ Zerathorn the Pale 26400 60 10 │ Caelwyn of the Crystal Spire 26624 55 11 │ Orlien Silverchant 26912 46 12 │ Morvain Duskwalker 27288 74 13 │ Rhovar Mistborn 27344 50 14 │ Zytherin the Forgotten 27344 56 15 │ Xandor the Arcane 27344 68 16 │ Kerron the Unseen 27344 71 17 │ Orren Emberforge 27344 58 18 │ Eldaric Runehand 27344 57 19 │ Velindra the Azure 27344 67 20 │ Lunara Dreambinder 27344 65 21 │ Althira Starweaver 27344 67 22 │ Gorvath Ironchant 27344 82 23 │ Erenwyn the Whispering 27400 66 24 │ Velmaris Lightbinder 27400 63 25 │ Faelora Nightbloom 27464 67 26 │ Sareth the Verdant 27568 57 27 │ Valtheris of the Amber Flame 27568 77 28 │ Mirelda Starbloom 27568 85 29 │ Maranelle Frostpetal 27568 65 30 │ Nimriel the Golden 27568 94 31 │ Sylthara the Veiled 27904 70 32 │ Galdur the Wise 29584 92 33 │ Talmek the Shattered 29840 93 34 │ Cyralis Moonbinder 29920 80 35 │ Dromek the Bound 30088 78 36 │ Yseline Frostwhisper 35808 126 37 │ Selvethra of the Whispering Woods 39496 127 38 │ Talvorn Runebreaker 46040 97 39 │ Thamior Embercloak 50208 111 40 │ Korthen Deepflame 85024 101 41 │ Korvath the Obsidian 85024 114 42 │ Ilyrien Dawnpetal 141424 104 43 │ Bramor the Tempest 1682056 122
ComplexF64
A konečně experiment se zobecněným kombinačním číslem, kde typ n uvažujeme ComplexF64.
sort!(df, :test_cfloat64_t)
df[!, :test_cfloat64_t] /= df[1, :test_cfloat64_t]
record_rank!(df, :test_cfloat64_t)
show(df[!,[:nick, :test_cfloat64_t, :score, :test_cfloat64_c]], allrows=true, allcols=true)43×4 DataFrame Row │ nick test_cfloat64_t score test_cfloat64_c │ String Float64 Int64 Bool ─────┼──────────────────────────────────────────────────────────────────────────── 1 │ kalvotom 1.0 32 true 2 │ Kerron the Unseen 1.00333 73 true 3 │ Velmaris Lightbinder 1.00665 66 true 4 │ Eldaric Runehand 1.00718 61 true 5 │ Rhovar Mistborn 1.02894 55 true 6 │ Erenwyn the Whispering 1.03328 72 true 7 │ Orren Emberforge 1.03387 65 true 8 │ Velindra the Azure 1.03448 75 true 9 │ Aeloria of the Seven Sigils 1.03675 53 true 10 │ Gorvath Ironchant 1.03675 92 true 11 │ Valtheris of the Amber Flame 1.07451 88 true 12 │ Maerilith Stormweaver 1.35606 39 true 13 │ Zerathorn the Pale 1.80432 73 true 14 │ Xandor the Arcane 1.83031 82 true 15 │ Sareth the Verdant 1.83208 72 true 16 │ Orlien Silverchant 1.83383 62 true 17 │ Faelora Nightbloom 1.83837 84 true 18 │ Talvorn Runebreaker 1.83877 115 true 19 │ Vessryn Bloodsong 1.84328 68 true 20 │ chatgpt 1.86362 68 true 21 │ Zytherin the Forgotten 1.86913 77 true 22 │ Ilyrien Dawnpetal 1.87495 126 true 23 │ Sylthara the Veiled 1.87523 93 true 24 │ Morvain Duskwalker 1.87536 98 true 25 │ Galdur the Wise 1.87856 117 true 26 │ Mirelda Starbloom 1.8787 111 true 27 │ Lunara Dreambinder 1.87898 92 true 28 │ Korvath the Obsidian 1.9097 142 true 29 │ Nimriel the Golden 1.91354 123 true 30 │ Maranelle Frostpetal 1.92153 95 true 31 │ Caelwyn of the Crystal Spire 1.96291 86 true 32 │ Dravok the Gloomed 2.16315 62 true 33 │ julia 2.44333 86 true 34 │ Korthen Deepflame 2.55003 135 true 35 │ Vyrion the Eternal 9.21413 85 true 36 │ Talmek the Shattered 11.4099 129 true 37 │ Dromek the Bound 11.4099 114 true 38 │ Cyralis Moonbinder 11.5063 117 true 39 │ Yseline Frostwhisper 11.6235 164 true 40 │ Bramor the Tempest 11.6441 161 true 41 │ Thamior Embercloak 11.6786 151 true 42 │ Selvethra of the Whispering Woods 11.7372 168 true 43 │ Althira Starweaver 483.945 109 true
A pak paměť, čím méně, tím lépe.
sort!(df, :test_int64_m)
record_rank!(df, :test_int64_m)
show(df[!, [:nick, :test_int64_m, :score]], allrows=true)43×3 DataFrame Row │ nick test_int64_m score │ String Int64? Int64 ─────┼──────────────────────────────────────────────────────── 1 │ kalvotom 0 33 2 │ Kerron the Unseen 0 74 3 │ Velmaris Lightbinder 0 67 4 │ Eldaric Runehand 0 62 5 │ Rhovar Mistborn 0 56 6 │ Erenwyn the Whispering 0 73 7 │ Orren Emberforge 0 66 8 │ Velindra the Azure 0 76 9 │ Aeloria of the Seven Sigils 0 54 10 │ Gorvath Ironchant 0 93 11 │ Valtheris of the Amber Flame 0 89 12 │ Maerilith Stormweaver 0 40 13 │ Zerathorn the Pale 0 74 14 │ Xandor the Arcane 0 83 15 │ Sareth the Verdant 0 73 16 │ Orlien Silverchant 0 63 17 │ Faelora Nightbloom 0 85 18 │ Talvorn Runebreaker 0 116 19 │ Vessryn Bloodsong 0 69 20 │ chatgpt 0 69 21 │ Zytherin the Forgotten 0 78 22 │ Ilyrien Dawnpetal 0 127 23 │ Sylthara the Veiled 0 94 24 │ Morvain Duskwalker 0 99 25 │ Galdur the Wise 0 118 26 │ Mirelda Starbloom 0 112 27 │ Lunara Dreambinder 0 93 28 │ Korvath the Obsidian 0 143 29 │ Nimriel the Golden 0 124 30 │ Maranelle Frostpetal 0 96 31 │ Caelwyn of the Crystal Spire 0 87 32 │ Dravok the Gloomed 0 63 33 │ Korthen Deepflame 0 136 34 │ Vyrion the Eternal 0 86 35 │ Talmek the Shattered 0 130 36 │ Dromek the Bound 0 115 37 │ Cyralis Moonbinder 0 118 38 │ Thamior Embercloak 0 152 39 │ Selvethra of the Whispering Woods 0 169 40 │ Althira Starweaver 0 110 41 │ julia 80 88 42 │ Bramor the Tempest 608 164 43 │ Yseline Frostwhisper 7768 168
Závěrečná tabulka
Zaznamenávali jsme v každé kategorii (sdílené) pořadí. Čím nižší hodnota, tím lepší výsledek.
sort!(df, :score)
show(df[!,[:nick, :score]], allrows=true)43×2 DataFrame Row │ nick score │ String Int64 ─────┼────────────────────────────────────────── 1 │ kalvotom 33 2 │ Maerilith Stormweaver 40 3 │ Aeloria of the Seven Sigils 54 4 │ Rhovar Mistborn 56 5 │ Eldaric Runehand 62 6 │ Orlien Silverchant 63 7 │ Dravok the Gloomed 63 8 │ Orren Emberforge 66 9 │ Velmaris Lightbinder 67 10 │ Vessryn Bloodsong 69 11 │ chatgpt 69 12 │ Erenwyn the Whispering 73 13 │ Sareth the Verdant 73 14 │ Kerron the Unseen 74 15 │ Zerathorn the Pale 74 16 │ Velindra the Azure 76 17 │ Zytherin the Forgotten 78 18 │ Xandor the Arcane 83 19 │ Faelora Nightbloom 85 20 │ Vyrion the Eternal 86 21 │ Caelwyn of the Crystal Spire 87 22 │ julia 88 23 │ Valtheris of the Amber Flame 89 24 │ Gorvath Ironchant 93 25 │ Lunara Dreambinder 93 26 │ Sylthara the Veiled 94 27 │ Maranelle Frostpetal 96 28 │ Morvain Duskwalker 99 29 │ Althira Starweaver 110 30 │ Mirelda Starbloom 112 31 │ Dromek the Bound 115 32 │ Talvorn Runebreaker 116 33 │ Galdur the Wise 118 34 │ Cyralis Moonbinder 118 35 │ Nimriel the Golden 124 36 │ Ilyrien Dawnpetal 127 37 │ Talmek the Shattered 130 38 │ Korthen Deepflame 136 39 │ Korvath the Obsidian 143 40 │ Thamior Embercloak 152 41 │ Bramor the Tempest 164 42 │ Yseline Frostwhisper 168 43 │ Selvethra of the Whispering Woods 169