"Advent of Code 2024" by "flowblok"
Release along with an interpreter.
Release along with the source text.
The story headline is "A festive coding misadventure".
The story genre is "Other".
The release number is 1.
The story creation year is 2024.
A door is usually open.
The description of a room is usually "You can push buttons by typing something like '[bold type]push button 1[roman type]'."
Chapter - Buttons
A button is a kind of device.
A button is either incomplete or complete. A button is usually incomplete.
A button is usually fixed in place.
Instead of pushing a button, try switching on the noun.
Report switching on a button:
say "The button begins to glow, and you sense you should enter the input for this day's problem. If there are multiple lines of input, enter a blank line afterwards (if the input is separated by blank lines, enter two)." instead;
The examine devices rule does nothing when the noun is a button.
To unpush (x - button):
now x is switched off;
if x is incomplete:
say "[line break]A star has appeared! [line break]";
now x is complete;
follow the scene change machinery rule;
A part 1 button is a kind of button.
The printed name of a part 1 button is "Part 1 button".
The description of a part 1 button is "A button with the number 1 printed on it. It looks like you could push this.".
A part 2 button is a kind of button.
The printed name of a part 2 button is "Part 2 button".
The description of a part 2 button is "A button with the number 2 printed on it. It looks like you could push this.".
Cheating is an action applying to one thing.
Understand "cheat [something]" as cheating.
Carry out cheating:
unpush the noun;
Cheating all is an action applying to nothing.
Understand "cheat all" as cheating all.
Carry out cheating all:
repeat through the Table of Stars:
if button entry is not D25P2 button:
now button entry is complete;
Chapter - Vortex
The Vortex is a room. "Many doors of all shapes and sizes float around you, each with a number on them. You think you can drift towards one of them by typing something like '[bold type]enter door 1[roman type]'.".
Table of Stars
Day (number) Part (number) Button (button)
-- -- --
To decide what text is the star progress:
let stars be "";
let i be 2;
let n be the number of rows in the Table of Stars;
repeat with day running from 1 to 25:
repeat with part running from 1 to 2:
let star be "";
if i <= n:
choose row i in the Table of Stars;
if day entry is day and part entry is part:
increment i;
if button entry is complete:
now star is "";
now stars is "[stars][star]";
decide on stars;
Rule for printing the locale description of the Vortex:
say "Amongst the swirls of colour are a collection of stars: [star progress][paragraph break]";
let door numbers be a list of numbers;
repeat with door running through the list of doors in the Vortex:
let name be the printed name of door;
add word number 2 in name understood as a number to door numbers;
sort door numbers;
say "You can see doors with the numbers [door numbers].[paragraph break]";
stop the action;
Chapter - Day 01
Day 1 is a room.
d1 is a direction. d1 has opposite outside. Index map with d1 mapped as inside.
Door 1 is a door. Door 1 is d1 of the Vortex and outside of Day 1.
Section - Part 1
D01P1 button is a part 1 button.
D01P1 button is here.
D01P1 scene is a recurring scene.
D01P1 scene begins when D01P1 button is switched on.
D01P1 scene ends when D01P1 button is switched off.
Table of Stars (continued)
Day Part Button
1 1 D01P1 button
Entering a D01P1 line is an action applying to one topic.
Understand "[text]" as entering a D01P1 line when D01P1 scene is happening.
The D01P1 left list is a list of numbers which varies.
The D01P1 right list is a list of numbers which varies.
When D01P1 scene begins:
now the D01P1 left list is {};
now the D01P1 right list is {}.
Carry out entering a D01P1 line:
let x be the word number 1 in the topic understood;
let y be the word number 2 in the topic understood;
add x understood as a number to the D01P1 left list;
add y understood as a number to the D01P1 right list;
Completing the D01P1 calculation is an action applying to nothing.
Before entering a blank line:
if D01P1 scene is happening:
try completing the D01P1 calculation instead;
continue the action.
Carry out completing the D01P1 calculation:
sort the D01P1 left list;
sort the D01P1 right list;
let total be 0;
repeat with i running from 1 to the number of entries in D01P1 left list:
let x be entry i in D01P1 left list;
let y be entry i in D01P1 right list;
let distance be the integer absolute value of x - y;
now total is total + distance;
say "[total][line break]";
unpush D01P1 button;
[
D01P1 begins when play begins.
When D01P1 ends:
follow the immediately quit rule.
Test example with "3 4 / 4 3 / 2 5 / 1 3 / 3 9 / 3 3 / /"
]
Section - Part 2
D01P2 button is a part 2 button.
D01P2 button is here.
D01P2 scene is a recurring scene.
D01P2 scene begins when D01P2 button is switched on.
D01P2 scene ends when D01P2 button is switched off.
Table of Stars (continued)
Day Part Button
1 2 D01P2 button
Entering a D01P2 line is an action applying to one topic.
Understand "[text]" as entering a D01P2 line when D01P2 scene is happening.
The D01P2 left list is a list of numbers which varies.
The D01P2 right list is a list of numbers which varies.
When D01P2 scene begins:
now the D01P2 left list is {};
now the D01P2 right list is {}.
Carry out entering a D01P2 line:
let x be the word number 1 in the topic understood;
let y be the word number 2 in the topic understood;
add x understood as a number to the D01P2 left list;
add y understood as a number to the D01P2 right list;
Completing the D01P2 calculation is an action applying to nothing.
Before entering a blank line:
if D01P2 scene is happening:
try completing the D01P2 calculation instead;
continue the action.
Carry out completing the D01P2 calculation:
sort the D01P2 right list;
let total be 0;
repeat with i running from 1 to the number of entries in D01P2 left list:
let x be entry i in D01P2 left list;
let y be the sorted count of x in D01P2 right list;
now total is total + (x * y);
say "[total][line break]";
unpush D01P2 button;
[
D01P2 begins when play begins.
When D01P2 ends:
end the story.
Test example with "3 4 / 4 3 / 2 5 / 1 3 / 3 9 / 3 3 / /"
]
Chapter - Day 02
Day 2 is a room.
d2 is a direction. d2 has opposite outside. Index map with d2 mapped as inside.
Door 2 is a door. Door 2 is d2 of the Vortex and outside of Day 2.
Section - Part 1
D02P1 button is a part 1 button.
D02P1 button is here.
D02P1 scene is a recurring scene.
D02P1 scene begins when D02P1 button is switched on.
D02P1 scene ends when D02P1 button is switched off.
Table of Stars (continued)
Day Part Button
2 1 D02P1 button
Entering a D02P1 line is an action applying to one topic.
Understand "[text]" as entering a D02P1 line when D02P1 scene is happening.
The D02P1 safe count is a number which varies.
When D02P1 scene begins:
now the D02P1 safe count is 0;
Carry out entering a D02P1 line:
let levels be parse number applied to the words of the topic understood;
if levels is D02P1 safe:
increment D02P1 safe count;
To decide if (levels - list of numbers) is D02P1 safe:
if levels is monotonically increasing or levels is monotonically decreasing:
let length be the number of entries in levels;
repeat with i running from 1 to length - 1:
let x be entry i of levels;
let y be entry i + 1 of levels;
let distance be the integer absolute value of (x - y);
if distance < 1 or distance > 3, decide no;
decide yes;
decide no;
Completing the D02P1 calculation is an action applying to nothing.
Before entering a blank line:
if D02P1 scene is happening:
try completing the D02P1 calculation instead;
continue the action.
Carry out completing the D02P1 calculation:
say "[D02P1 safe count][line break]";
unpush D02P1 button;
[
D02P1 begins when play begins.
When D02P1 ends:
follow the immediately quit rule.
Test example with "7 6 4 2 1 / 1 2 7 8 9 / 9 7 6 2 1 / 1 3 2 4 5 / 8 6 4 4 1 / 1 3 6 7 9 / /"
]
Section - Part 2
D02P2 button is a part 2 button.
D02P2 button is here.
D02P2 scene is a recurring scene.
D02P2 scene begins when D02P2 button is switched on.
D02P2 scene ends when D02P2 button is switched off.
Table of Stars (continued)
Day Part Button
2 2 D02P2 button
Entering a D02P2 line is an action applying to one topic.
Understand "[text]" as entering a D02P2 line when D02P2 scene is happening.
The D02P2 safe count is a number which varies.
When D02P2 scene begins:
now the D02P2 safe count is 0;
Carry out entering a D02P2 line:
let levels be parse number applied to the words of the topic understood;
if levels is D02P2 safe:
increment D02P2 safe count;
To decide if (levels - list of numbers) is D02P2 safe:
if levels is D02P1 safe, decide yes;
let length be the number of entries in levels;
repeat with i running from 1 to length:
let sublevels be levels;
remove entry i from sublevels;
if sublevels is D02P1 safe, decide yes;
decide no;
Completing the D02P2 calculation is an action applying to nothing.
Before entering a blank line:
if D02P2 scene is happening:
try completing the D02P2 calculation instead;
continue the action.
Carry out completing the D02P2 calculation:
say "[D02P2 safe count][line break]";
unpush D02P2 button;
[
D02P2 begins when play begins.
When D02P2 ends:
follow the immediately quit rule.
Test example with "7 6 4 2 1 / 1 2 7 8 9 / 9 7 6 2 1 / 1 3 2 4 5 / 8 6 4 4 1 / 1 3 6 7 9 / /"
]
Chapter - Day 03
Day 3 is a room.
d3 is a direction. d3 has opposite outside. Index map with d3 mapped as inside.
Door 3 is a door. Door 3 is d3 of the Vortex and outside of Day 3.
Section - Part 1
D03P1 button is a part 1 button.
D03P1 button is here.
D03P1 scene is a recurring scene.
D03P1 scene begins when D03P1 button is switched on.
D03P1 scene ends when D03P1 button is switched off.
Table of Stars (continued)
Day Part Button
3 1 D03P1 button
Entering a D03P1 line is an action applying to one topic.
The D03P1 result is a number which varies.
When D03P1 scene begins:
now D03P1 result is 0;
enable raw input;
To decide which number is the D03P1 eval of (input - text):
if input exactly matches the regular expression "mul\((\d+),(\d+)\)":
let x be text matching subexpression 1 understood as a number;
let y be text matching subexpression 2 understood as a number;
decide on x * y;
say "BAD INPUT: [input][line break]";
end the story;
decide on 0.
After reading a raw input when D03P1 scene is happening:
if raw input is "":
say "[D03P1 result][line break]";
unpush D03P1 button;
otherwise:
let matches be the regex matches of "mul\(\d+,\d+\)" on the raw input;
repeat with match running through matches:
let n be the D03P1 eval of match;
[say "[match] = [n][line break]";]
increase D03P1 result by n;
[say "-> [D03P1 result][line break]";]
When D03P1 scene ends:
disable raw input;
[
D03P1 begins when play begins.
When D03P1 ends:
follow the immediately quit rule.
]
Section - Part 2
D03P2 button is a part 2 button.
D03P2 button is here.
D03P2 scene is a recurring scene.
D03P2 scene begins when D03P2 button is switched on.
D03P2 scene ends when D03P2 button is switched off.
Table of Stars (continued)
Day Part Button
3 2 D03P2 button
Entering a D03P2 line is an action applying to one topic.
The D03P2 result is a number which varies.
[My experience using regexes with D03P1 was terrible.
Let's write our own state machine, so at least the problems will be my fault.
STATE_NORMAL
-> 'm' = STATE_M -> 'u' = STATE_MU -> 'l' = STATE_MUL
-> '(' = STATE_MUL0 ->* [0-9] = STATE_MUL1
-> [0-9] = STATE_MUL1
->* ',' = STATE_MUL2 -> [0-9] = STATE_MUL3
-> [0-9] = STATE_MUL3
->* ')' = STATE_NORMAL
-> 'd' = STATE_D -> 'o' = STATE_DO
-> '(' = STATE_DO0 ->* ')' = STATE_NORMAL
-> 'n' = STATE_DON -> "'" = STATE_DON_ -> 't' = STATE_DONT
-> '(' = STATE_DONT0 ->* ')' = STATE_NORMAL
Unspecified characters are unstarred transitions to STATE_NORMAL.
The following starred transitions require special handling:
STATE_MUL0 -> STATE_MUL1
store the index of the first argument
STATE_MUL1 -> STATE_MUL2
store the index between the arguments
STATE_MUL3 -> STATE_NORMAL
if mul is enabled, add the result to the accumulator
STATE_DO0 -> STATE_NORMAL
enable mul
STATE_DONT0 -> STATE_NORMAL
disable mul
]
A D03P2 state is a kind of value. The D03P2 states are STATE_NORMAL, STATE_M, STATE_MU, STATE_MUL, STATE_MUL0, STATE_MUL1, STATE_MUL2, STATE_MUL3, STATE_D, STATE_DO, STATE_DO0, STATE_DON, STATE_DON_, STATE_DONT, STATE_DONT0, STATE_DONT1.
The D03P2 current state is a D03P2 state that varies.
The D03P2 first index is a number that varies.
The D03P2 second index is a number that varies.
The D03P2 third index is a number that varies.
The D03P2 mul enabled is a truth state that varies.
When D03P2 scene begins:
now D03P2 result is 0;
now D03P2 current state is STATE_NORMAL;
now D03P2 mul enabled is true;
enable raw input;
To process D03P2 mul:
if D03P2 mul enabled is true:
let a be the substring of raw input from D03P2 first index to D03P2 second index - 1;
let b be the substring of raw input from D03P2 second index + 1 to D03P2 third index - 1;
let ab be (a understood as a number) * (b understood as a number);
[say "[a]*[b]=[ab][line break]";]
increase D03P2 result by ab;
[say " -> [D03P2 result][line break]";]
After reading a raw input when D03P2 scene is happening:
if raw input is "":
say "[D03P2 result][line break]";
unpush D03P2 button;
otherwise:
repeat with i running from 1 to the number of characters in the raw input:
let c be character number i in raw input;
[say "[i]/[c]/[D03P2 current state]/[D03P2 first index]/[D03P2 second index]/[D03P2 mul enabled][line break]";]
if D03P2 current state is STATE_NORMAL:
if c is "m", now D03P2 current state is STATE_M;
if c is "d", now D03P2 current state is STATE_D;
else if D03P2 current state is STATE_M:
if c is "u":
now D03P2 current state is STATE_MU;
else:
now D03P2 current state is STATE_NORMAL;
else if D03P2 current state is STATE_MU:
if c is "l":
now D03P2 current state is STATE_MUL;
else:
now D03P2 current state is STATE_NORMAL;
else if D03P2 current state is STATE_MUL:
if c is "(":
now D03P2 current state is STATE_MUL0;
else:
now D03P2 current state is STATE_NORMAL;
else if D03P2 current state is STATE_MUL0:
if c is a digit:
now D03P2 first index is i;
now D03P2 current state is STATE_MUL1;
else:
now D03P2 current state is STATE_NORMAL;
else if D03P2 current state is STATE_MUL1:
if c is ",":
now D03P2 second index is i;
now D03P2 current state is STATE_MUL2;
else if c is not a digit:
now D03P2 current state is STATE_NORMAL;
else if D03P2 current state is STATE_MUL2:
if c is a digit:
now D03P2 current state is STATE_MUL3;
else:
now D03P2 current state is STATE_NORMAL;
else if D03P2 current state is STATE_MUL3:
if c is ")":
now D03P2 third index is i;
process D03P2 mul;
now D03P2 current state is STATE_NORMAL;
else if c is not a digit:
now D03P2 current state is STATE_NORMAL;
else if D03P2 current state is STATE_D:
if c is "o":
now D03P2 current state is STATE_DO;
else:
now D03P2 current state is STATE_NORMAL;
else if D03P2 current state is STATE_DO:
if c is "(":
now D03P2 current state is STATE_DO0;
else if c is "n":
now D03P2 current state is STATE_DON;
else:
now D03P2 current state is STATE_NORMAL;
else if D03P2 current state is STATE_DO0:
if c is ")":
now D03P2 mul enabled is true;
now D03P2 current state is STATE_NORMAL;
else if D03P2 current state is STATE_DON:
if c is "[']":
now D03P2 current state is STATE_DON_;
else:
now D03P2 current state is STATE_NORMAL;
else if D03P2 current state is STATE_DON_:
if c is "t":
now D03P2 current state is STATE_DONT;
else:
now D03P2 current state is STATE_NORMAL;
else if D03P2 current state is STATE_DONT:
if c is "(":
now D03P2 current state is STATE_DONT0;
else:
now D03P2 current state is STATE_NORMAL;
else if D03P2 current state is STATE_DONT0:
if c is ")":
now D03P2 mul enabled is false;
now D03P2 current state is STATE_NORMAL;
When D03P2 scene ends:
disable raw input;
[
D03P2 begins when play begins.
When D03P2 ends:
follow the immediately quit rule.
]
Chapter - Day 04
Day 4 is a room.
d4 is a direction. d4 has opposite outside. Index map with d4 mapped as inside.
Door 4 is a door. Door 4 is d4 of the Vortex and outside of Day 4.
Section - Part 1
D04P1 button is a part 1 button.
D04P1 button is here.
D04P1 scene is a recurring scene.
D04P1 scene begins when D04P1 button is switched on.
D04P1 scene ends when D04P1 button is switched off.
Table of Stars (continued)
Day Part Button
4 1 D04P1 button
Entering a D04P1 line is an action applying to one topic.
Understand "[text]" as entering a D04P1 line when D04P1 scene is happening.
The D04P1 grid is a list of text which varies.
When D04P1 scene begins:
now D04P1 grid is {};
Carry out entering a D04P1 line:
add the topic understood in upper case to D04P1 grid.
Completing the D04P1 calculation is an action applying to nothing.
To decide what number is the D04P1 grid width:
decide on the number of characters in entry 1 of D04P1 grid.
To decide what number is the D04P1 grid height:
decide on the number of entries in D04P1 grid.
To decide what number is the D04P1 horizontal count:
let result be 0;
repeat with line running through D04P1 grid:
increase result by the number of times line matches the text "XMAS";
increase result by the number of times line matches the text "SAMX";
decide on result.
To decide what number is the D04P1 vertical count:
let result be 0;
repeat with x running from 1 to the D04P1 grid width:
let line be "";
repeat with y running from 1 to the D04P1 grid height:
now line is "[line][character number x in entry y of D04P1 grid]";
increase result by the number of times line matches the text "XMAS";
increase result by the number of times line matches the text "SAMX";
decide on result.
To decide what number is the D04P1 forward diagonal count:
let result be 0;
let count be D04P1 grid height + D04P1 grid width;
[skip the first/last three diagonals, since they have < 4 letters]
repeat with i running from 4 to count - 4:
let x be 1;
let y be i;
if y > D04P1 grid height:
now x is 1 + i - D04P1 grid height;
now y is D04P1 grid height;
let line be "";
while x <= D04P1 grid width and y > 0:
now line is "[line][character number x in entry y of D04P1 grid]";
increment x;
decrement y;
increase result by the number of times line matches the text "XMAS";
increase result by the number of times line matches the text "SAMX";
decide on result.
To decide what number is the D04P1 backward diagonal count:
let result be 0;
let count be D04P1 grid height + D04P1 grid width;
[skip the first/last three diagonals, since they have < 4 letters]
repeat with i running from 4 to count - 4:
let x be 1;
let y be D04P1 grid height - i - 1;
if y < 1:
now x is 2 - y;
now y is 1;
let line be "";
while x <= D04P1 grid width and y <= D04P1 grid height:
now line is "[line][character number x in entry y of D04P1 grid]";
increment x;
increment y;
increase result by the number of times line matches the text "XMAS";
increase result by the number of times line matches the text "SAMX";
decide on result.
Carry out completing the D04P1 calculation:
let h be D04P1 horizontal count;
let v be D04P1 vertical count;
let fd be D04P1 forward diagonal count;
let bd be D04P1 backward diagonal count;
say "[h + v + fd + bd][line break]";
now D04P1 grid is {};
unpush D04P1 button;
Before entering a blank line:
if D04P1 scene is happening:
try completing the D04P1 calculation instead;
continue the action.
[
D04P1 begins when play begins.
When D04P1 ends:
end the story.
Test example with "MMMSXXMASM / MSAMXMSMSA / AMXSXMAAMM / MSAMASMSMX / XMASAMXAMM / XXAMMXXAMA / SMSMSASXSS / SAXAMASAAA / MAMMMXMMMM / MXMXAXMASX / /"
]
Section - Part 2
D04P2 button is a part 2 button.
D04P2 button is here.
D04P2 scene is a recurring scene.
D04P2 scene begins when D04P2 button is switched on.
D04P2 scene ends when D04P2 button is switched off.
Table of Stars (continued)
Day Part Button
4 2 D04P2 button
Entering a D04P2 line is an action applying to one topic.
Understand "[text]" as entering a D04P2 line when D04P2 scene is happening.
The D04P2 grid is a list of text which varies.
When D04P2 scene begins:
now D04P2 grid is {};
Carry out entering a D04P2 line:
add the topic understood in upper case to D04P2 grid.
Completing the D04P2 calculation is an action applying to nothing.
To decide what number is the D04P2 grid width:
decide on the number of characters in entry 1 of D04P2 grid.
To decide what number is the D04P2 grid height:
decide on the number of entries in D04P2 grid.
To decide which number is the D04P2 result:
let result be 0;
repeat with y running from 2 to D04P2 grid height - 1:
repeat with x running from 2 to D04P2 grid width - 1:
let middle be character number x in entry y of D04P2 grid;
if middle is "A":
let upper left be character number x - 1 in entry y - 1 of D04P2 grid;
let upper right be character number x + 1 in entry y - 1 of D04P2 grid;
let lower left be character number x - 1 in entry y + 1 of D04P2 grid;
let lower right be character number x + 1 in entry y + 1 of D04P2 grid;
let word be "[upper left][lower right][upper right][lower left]";
if word is "MSMS" or word is "MSSM" or word is "SMMS" or word is "SMSM":
increment result;
decide on result.
Carry out completing the D04P2 calculation:
say "[D04P2 result][line break]";
now D04P2 grid is {};
unpush D04P2 button;
Before entering a blank line:
if D04P2 scene is happening:
try completing the D04P2 calculation instead;
continue the action.
[
D04P2 begins when play begins.
When D04P2 ends:
end the story.
Test example with "MMMSXXMASM / MSAMXMSMSA / AMXSXMAAMM / MSAMASMSMX / XMASAMXAMM / XXAMMXXAMA / SMSMSASXSS / SAXAMASAAA / MAMMMXMMMM / MXMXAXMASX / /"
]
Chapter - Day 05
Day 5 is a room.
d5 is a direction. d5 has opposite outside. Index map with d5 mapped as inside.
Door 5 is a door. Door 5 is d5 of the Vortex and outside of Day 5.
Section - Part 1
D05P1 button is a part 1 button.
D05P1 button is here.
D05P1 scene is a recurring scene.
D05P1 scene begins when D05P1 button is switched on.
D05P1 scene ends when D05P1 button is switched off.
Table of Stars (continued)
Day Part Button
5 1 D05P1 button
A D05P1 state is a kind of value. The D05P1 states are PAGE_ORDERING and UPDATES.
The D05P1 current state is a D05P1 state that varies.
The D05P1 result is a number that varies.
When D05P1 scene begins:
now D05P1 current state is PAGE_ORDERING;
now D05P1 result is 0;
enable raw input;
The D05P1 source order is a list of list of numbers that varies.
The D05P1 destination order is a list of list of numbers that varies.
[I7-2471 strikes again]
To decide which number is the D05P1 lower bound index of (target - number) in (items - list of list of numbers):
let length be the number of entries in items;
let low be 0;
while length > 0:
let half length be length / 2;
let mid be low + half length;
if entry 1 in (entry (mid + 1) in items) < target:
now low is mid + 1;
now length is length - (half length + 1);
otherwise:
now length is half length;
decide on (low + 1).
To decide whether (update - list of numbers) is D05P1 correctly ordered:
let enforcable rules be a list of numbers;
repeat with page running through update:
[say "checking [page][line break]";]
[check if we have a page|X ordering rule where we have seen X already]
let i be the D05P1 lower bound index of page in D05P1 source order;
let n be the number of entries in D05P1 source order;
while i <= n and entry 1 in (entry i in D05P1 source order) is page:
let found rule be entry 2 in (entry i in D05P1 source order);
[say "found [found rule][line break]";]
if found rule is in already-sorted enforcable rules:
decide no;
increment i;
[any X|page rule is now enforcable]
now i is the D05P1 lower bound index of page in D05P1 destination order;
while i <= n and entry 1 in (entry i in D05P1 destination order) is page:
let newly enforcable rule be entry 2 in (entry i in D05P1 destination order);
[say "adding [newly enforcable rule][line break]";]
add newly enforcable rule to enforcable rules;
increment i;
sort enforcable rules;
decide yes;
After reading a raw input when D05P1 scene is happening:
if raw input is "":
if D05P1 current state is PAGE_ORDERING:
sort D05P1 source order;
sort D05P1 destination order;
now D05P1 current state is UPDATES;
else:
complete the D05P1 calculation;
else:
if D05P1 current state is PAGE_ORDERING:
evaluate a D05P1 page ordering rule;
else:
evaluate a D05P1 update;
To evaluate a D05P1 page ordering rule:
let line be raw input;
replace the text "|" in line with " ";
let the rule id be the number of entries in D05P1 source order;
let the new source be a list of numbers;
add (word number 1 in line) understood as a number to the new source;
add the rule id to the new source;
add the new source to the D05P1 source order;
let the new dest be a list of numbers;
add (word number 2 in line) understood as a number to the new dest;
add the rule id to the new dest;
add the new dest to D05P1 destination order;
To evaluate a D05P1 update:
let line be raw input;
let pages be parse number applied to the words of line;
if pages is D05P1 correctly ordered:
let middle index be (number of entries in pages + 1) / 2;
let middle be entry middle index in pages;
increase D05P1 result by middle;
[say "[pages] #[number of entries in pages] -> [middle index]/ [middle] -> [D05P1 result][line break]";]
To complete the D05P1 calculation:
say D05P1 result;
disable raw input;
unpush D05P1 button;
[
D05P1 begins when play begins.
When D05P1 ends:
end the story.
Test example with "47|53 / 97|13 / 97|61 / 97|47 / 75|29 / 61|13 / 75|53 / 29|13 / 97|29 / 53|29 / 61|53 / 97|53 / 61|29 / 47|13 / 75|47 / 97|75 / 47|61 / 75|61 / 47|29 / 75|13 / 53|13 / / 75,47,61,53,29 / 97,61,53,29,13 / 75,29,13 / 75,97,47,61,53 / 61,13,29 / 97,13,75,29,47 / /"
]
Section - Part 2
D05P2 button is a part 2 button.
D05P2 button is here.
D05P2 scene is a recurring scene.
D05P2 scene begins when D05P2 button is switched on.
D05P2 scene ends when D05P2 button is switched off.
[A D05P2 state is a kind of value. The D05P2 states are PAGE_ORDERING and UPDATES.]
The D05P2 current state is a D05P1 state that varies.
The D05P2 result is a number that varies.
Table of Stars (continued)
Day Part Button
5 2 D05P2 button
When D05P2 scene begins:
now D05P2 current state is PAGE_ORDERING;
now D05P2 result is 0;
enable raw input;
The D05P2 source order is a list of list of numbers that varies.
The D05P2 destination order is a list of list of numbers that varies.
[I7-2471 strikes again]
To decide which number is the D05P2 lower bound index of (target - number) in (items - list of list of numbers):
let length be the number of entries in items;
let low be 0;
while length > 0:
let half length be length / 2;
let mid be low + half length;
if entry 1 in (entry (mid + 1) in items) < target:
now low is mid + 1;
now length is length - (half length + 1);
otherwise:
now length is half length;
decide on (low + 1).
To decide whether (update - list of numbers) is D05P2 correctly ordered:
let enforcable rules be a list of numbers;
repeat with page running through update:
[say "checking [page][line break]";]
[check if we have a page|X ordering rule where we have seen X already]
let i be the D05P2 lower bound index of page in D05P2 source order;
let n be the number of entries in D05P2 source order;
while i <= n and entry 1 in (entry i in D05P2 source order) is page:
let found rule be entry 2 in (entry i in D05P2 source order);
[say "found [found rule][line break]";]
if found rule is in already-sorted enforcable rules:
decide no;
increment i;
[any X|page rule is now enforcable]
now i is the D05P2 lower bound index of page in D05P2 destination order;
while i <= n and entry 1 in (entry i in D05P2 destination order) is page:
let newly enforcable rule be entry 2 in (entry i in D05P2 destination order);
[say "adding [newly enforcable rule][line break]";]
add newly enforcable rule to enforcable rules;
increment i;
sort enforcable rules;
decide yes;
After reading a raw input when D05P2 scene is happening:
if raw input is "":
if D05P2 current state is PAGE_ORDERING:
sort D05P2 source order;
sort D05P2 destination order;
now D05P2 current state is UPDATES;
else:
complete the D05P2 calculation;
else:
if D05P2 current state is PAGE_ORDERING:
evaluate a D05P2 page ordering rule;
else:
evaluate a D05P2 update;
To evaluate a D05P2 page ordering rule:
[Parse "a|b" into numbers a and b]
let line be raw input;
replace the text "|" in line with " ";
let a be (word number 1 in line) understood as a number;
let b be (word number 2 in line) understood as a number;
[Add (a, X, b) to source order, where X is unique for each rule.]
let the rule id be the number of entries in D05P2 source order;
let the new source be a list of numbers;
add a to the new source;
add the rule id to the new source;
add b to the new source;
add the new source to the D05P2 source order;
[Add (b, X) to the destination order, where X is unique for each rule.]
let the new dest be a list of numbers;
add (word number 2 in line) understood as a number to the new dest;
add the rule id to the new dest;
add the new dest to D05P2 destination order;
To decide if D05P2 page (a - number) is before page (b - number) (this is D05P2 comparator):
[If we have a|X|b, then a < b. Otherwise, we declare a > b.]
let n be the number of entries in D05P2 source order;
let i be the D05P2 lower bound index of a in D05P2 source order;
while i <= n and entry 1 in (entry i of D05P2 source order) is a:
if entry 3 in (entry i of D05P2 source order) is b:
decide yes;
increment i;
decide no;
To evaluate a D05P2 update:
let line be raw input;
let pages be parse number applied to the words of line;
if not (pages is D05P2 correctly ordered):
now pages is pages sorted by D05P2 comparator;
let middle index be (number of entries in pages + 1) / 2;
let middle be entry middle index in pages;
increase D05P2 result by middle;
To complete the D05P2 calculation:
say D05P2 result;
disable raw input;
unpush D05P2 button;
[
D05P2 begins when play begins.
When D05P2 ends:
end the story.
]
Chapter - Day 06
Day 6 is a room.
d6 is a direction. d6 has opposite outside. Index map with d6 mapped as inside.
Door 6 is a door. Door 6 is d6 of the Vortex and outside of Day 6.
Section - Part 1
D06P1 button is a part 1 button.
D06P1 button is here.
D06P1 scene is a recurring scene.
D06P1 scene begins when D06P1 button is switched on.
D06P1 scene ends when D06P1 button is switched off.
Table of Stars (continued)
Day Part Button
6 1 D06P1 button
The D06P1 blocks is a list of number that varies.
The D06P1 visited is a list of number that varies.
The D06P1 grid width is a number that varies.
The D06P1 grid height is a number that varies.
The D06P1 guard X is a number that varies.
The D06P1 guard Y is a number that varies.
[Valid values: ^v<>]
The D06P1 guard direction is a text that varies.
When D06P1 scene begins:
now D06P1 blocks is {};
now D06P1 visited is {};
now D06P1 grid width is 0;
now D06P1 grid height is 0;
now D06P1 guard X is 0;
now D06P1 guard Y is 0;
enable raw input;
After reading a raw input when D06P1 scene is happening:
if raw input is "":
complete the D06P1 calculation;
else:
read a D06P1 line;
To read a D06P1 line:
let line be raw input;
if D06P1 grid width is 0:
now D06P1 grid width is the number of characters in line;
increment D06P1 grid height;
repeat with x running from 1 to D06P1 grid width:
let c be character number x in line;
if c is "#":
let idx be the D06P1 encoded position of x and D06P1 grid height;
add idx to D06P1 blocks;
else if c is "^" or c is "v" or c is "<" or c is ">":
now D06P1 guard X is x;
now D06P1 guard Y is D06P1 grid height;
now D06P1 guard direction is c;
let idx be the D06P1 encoded position of D06P1 guard X and D06P1 guard Y;
add idx to D06P1 visited;
To decide which number is the D06P1 encoded position of (x - number) and (y - number):
decide on (y * D06P1 grid width) + x;
To show the D06P1 grid:
sort D06P1 visited;
repeat with y running from 1 to the D06P1 grid height:
let line be "";
repeat with x running from 1 to the D06P1 grid width:
let idx be the D06P1 encoded position of x and y;
if x is D06P1 guard X and y is D06P1 guard Y:
now line is "[line][D06P1 guard direction]";
else if idx is in already-sorted D06P1 blocks:
now line is "[line]#";
else if idx is in already-sorted D06P1 visited:
now line is "[line]X";
else:
now line is "[line].";
say "[line][line break]";
To decide if taking a D06P1 guard step is not the last:
let new x be D06P1 guard X;
let new y be D06P1 guard Y;
if D06P1 guard direction is "^":
decrement new y;
else if D06P1 guard direction is "v":
increment new y;
else if D06P1 guard direction is "<":
decrement new x;
else if D06P1 guard direction is ">":
increment new x;
if 1 <= new x and new x <= D06P1 grid width and 1 <= new y and new y <= D06P1 grid height:
let idx be the D06P1 encoded position of new x and new y;
if idx is in already-sorted D06P1 blocks:
[Turn right 90 degrees]
if D06P1 guard direction is "^":
now D06P1 guard direction is ">";
else if D06P1 guard direction is ">":
now D06P1 guard direction is "v";
else if D06P1 guard direction is "v":
now D06P1 guard direction is "<";
else if D06P1 guard direction is "<":
now D06P1 guard direction is "^";
else:
[Take a step forward]
add idx to D06P1 visited;
now D06P1 guard X is new x;
now D06P1 guard Y is new y;
else:
[Move to the invalid position]
now D06P1 guard X is new x;
now D06P1 guard Y is new y;
decide no;
decide yes;
To complete the D06P1 calculation:
[the encoding of D06P1 blocks means we don't need to sort it]
while taking a D06P1 guard step is not the last:
[show the D06P1 grid;
say "[paragraph break]";
read raw input;]
do nothing;
sort D06P1 visited;
let result be the distinct count of already-sorted D06P1 visited;
say "[result][line break]";
now D06P1 blocks is {};
now D06P1 visited is {};
disable raw input;
unpush D06P1 button;
[
D06P1 begins when play begins.
When D06P1 ends:
end the story.
Test example with "....#..... / .........# / .......... / ..#....... / .......#.. / .......... / .#..^..... / ........#. / #......... / ......#... / /"
]
Section - Part 2
D06P2 button is a part 2 button.
D06P2 button is here.
D06P2 scene is a recurring scene.
D06P2 scene begins when D06P2 button is switched on.
D06P2 scene ends when D06P2 button is switched off.
Table of Stars (continued)
Day Part Button
6 2 D06P2 button
[A list of encoded positions that are potential obstruction locations.]
The D06P2 obstructions is a list of number that varies.
[A list of {row1, row2, ...}, where each rowy is {x1, x2, ...}
where each (x, y) is a block.]
The D06P2 blocks by row is a list of list of number that varies.
[A list of {col1, col2, ...}, where each coly is {y1, y2, ...}
where each (x, y) is a block.]
The D06P2 blocks by column is a list of list of number that varies.
[A sorted list of encoded positions that the guard has already visited.]
The D06P2 visited is a list of number that varies.
[An unsorted list of encoded positions that the guard has already visited,
but won't yet be looked up.]
The D06P2 visited buffer is a list of number that varies.
The D06P2 grid width is a number that varies.
The D06P2 grid height is a number that varies.
The D06P2 guard X is a number that varies.
The D06P2 guard Y is a number that varies.
[Valid values: ^v<>]
The D06P2 guard direction is a text that varies.
When D06P2 scene begins:
now D06P2 obstructions is {};
now D06P2 blocks by row is {};
now D06P2 blocks by column is {};
now D06P2 visited is {};
now D06P2 visited buffer is {};
now D06P2 grid width is 0;
now D06P2 grid height is 0;
now D06P2 guard X is 0;
now D06P2 guard Y is 0;
enable raw input;
After reading a raw input when D06P2 scene is happening:
if raw input is "":
complete the D06P2 calculation;
else:
read a D06P2 line;
To read a D06P2 line:
let line be raw input;
if D06P2 grid width is 0:
now D06P2 grid width is the number of characters in line;
repeat with x running from 1 to D06P2 grid width:
let column blocks be a list of numbers;
add column blocks to D06P2 blocks by column;
increment D06P2 grid height;
let y be D06P2 grid height;
let row blocks be a list of numbers;
repeat with x running from 1 to D06P2 grid width:
let c be character number x in line;
if c is "#":
add x to row blocks;
add y to entry x of D06P2 blocks by column;
else if c is "^" or c is "v" or c is "<" or c is ">":
now D06P2 guard X is x;
now D06P2 guard Y is y;
now D06P2 guard direction is c;
let idx be the D06P2 encoded position of x and y;
add idx to D06P2 visited;
add row blocks to D06P2 blocks by row;
To decide which number is the D06P2 encoded position of (x - number) and (y - number):
decide on (y * D06P2 grid width) + x;
To decide which number is the D06P2 encoded pose of (x - number) and (y - number) with (d - text):
let position be the D06P2 encoded position of x and y;
decide on the D06P2 encoded pose of position with d;
To decide which number is the D06P2 encoded pose of (encoded position - number) with (d - text):
if d is "^", decide on (encoded position * 4) + 0;
if d is ">", decide on (encoded position * 4) + 1;
if d is "v", decide on (encoded position * 4) + 2;
if d is "<", decide on (encoded position * 4) + 3;
decide on 0;
To show the D06P2 grid:
sort D06P2 visited;
sort D06P2 obstructions;
repeat with y running from 1 to the D06P2 grid height:
let row blocks be entry y of D06P2 blocks by row;
let line be "";
repeat with x running from 1 to the D06P2 grid width:
let idx be the D06P2 encoded position of x and y;
if x is D06P2 guard X and y is D06P2 guard Y:
now line is "[line][D06P2 guard direction]";
else if x is listed in row blocks:
now line is "[line]#";
else if idx is in already-sorted D06P2 obstructions:
now line is "[line]O";
else if idx is in already-sorted D06P2 visited:
now line is "[line]X";
else:
now line is "[line].";
say "[line][line break]";
To decide if (x - number) and (y - number) are in D06P2 grid bounds:
if 1 <= x and x <= D06P2 grid width and 1 <= y and y <= D06P2 grid height, decide yes;
decide no;
To decide which number is the D06P2 next block up from (x - number) and (y - number):
let column blocks be entry x of D06P2 blocks by column;
let i be number of entries in column blocks;
while i >= 1:
let ny be entry i of column blocks;
if ny < y, decide on ny + 1;
decrement i;
decide on 0;
To decide which number is the D06P2 next block down from (x - number) and (y - number):
let column blocks be entry x of D06P2 blocks by column;
repeat with ny running through column blocks:
if ny > y, decide on ny - 1;
decide on 0;
To decide which number is the D06P2 next block left from (x - number) and (y - number):
let row blocks be entry y of D06P2 blocks by row;
let i be number of entries in row blocks;
while i >= 1:
let nx be entry i of row blocks;
if nx < x, decide on nx + 1;
decrement i;
decide on 0;
To decide which number is the D06P2 next block right from (x - number) and (y - number):
let row blocks be entry y of D06P2 blocks by row;
repeat with nx running through row blocks:
if nx > x, decide on nx - 1;
decide on 0;
To consider D06P2 obstruction at (nx - number) and (ny - number):
add nx to entry ny of D06P2 blocks by row;
sort entry ny of D06P2 blocks by row;
add ny to entry nx of D06P2 blocks by column;
sort entry nx of D06P2 blocks by column;
[say "testing block at ([nx],[ny])[line break]";
say "row blocks: [D06P2 blocks by row][line break]";
say "column blocks: [D06P2 blocks by column][line break]";]
let x be D06P2 guard X;
let y be D06P2 guard Y;
let d be "";
if D06P2 guard direction is "^":
now d is ">";
else if D06P2 guard direction is ">":
now d is "v";
else if D06P2 guard direction is "v":
now d is "<";
else if D06P2 guard direction is "<":
now d is "^";
[List of encoded poses we have visited in this loop.]
let seen poses be a list of number;
while true is true:
[say " ([x],[y],[d])[line break]";]
if d is "^":
now y is the D06P2 next block up from x and y;
now d is ">";
else if d is ">":
now x is the D06P2 next block right from x and y;
now d is "v";
else if d is "v":
now y is the D06P2 next block down from x and y;
now d is "<";
else if d is "<":
now x is the D06P2 next block left from x and y;
now d is "^";
if x is 0 or y is 0:
[say "left map[line break]";]
break;
let idx be the D06P2 encoded pose of x and y with d;
if idx is listed in seen poses:
[say "loop![line break]";]
add the D06P2 encoded position of nx and ny to D06P2 obstructions;
break;
add idx to seen poses;
[sort seen poses;]
remove nx from entry ny of D06P2 blocks by row;
remove ny from entry nx of D06P2 blocks by column;
To decide if taking a D06P2 guard step is not the last:
let new x be D06P2 guard X;
let new y be D06P2 guard Y;
if D06P2 guard direction is "^":
decrement new y;
else if D06P2 guard direction is "v":
increment new y;
else if D06P2 guard direction is "<":
decrement new x;
else if D06P2 guard direction is ">":
increment new x;
if new x and new y are in D06P2 grid bounds:
let row blocks be entry new y of D06P2 blocks by row;
if new x is listed in row blocks:
[Turn right 90 degrees]
if D06P2 guard direction is "^":
now D06P2 guard direction is ">";
else if D06P2 guard direction is ">":
now D06P2 guard direction is "v";
else if D06P2 guard direction is "v":
now D06P2 guard direction is "<";
else if D06P2 guard direction is "<":
now D06P2 guard direction is "^";
[Whenever we turn, merge the buffer into the visited list.]
sort D06P2 visited buffer;
add D06P2 visited buffer to D06P2 visited;
now D06P2 visited buffer is {};
sort D06P2 visited;
else:
let idx be the D06P2 encoded position of new x and new y;
[Consider alternative universes: if we had been blocked, would we enter a loop?]
if not (idx is in already-sorted D06P2 visited):
consider D06P2 obstruction at new x and new y;
[Take a step forward]
now D06P2 guard X is new x;
now D06P2 guard Y is new y;
[Record the new position]
add idx to D06P2 visited buffer;
else:
[Move to the invalid position]
now D06P2 guard X is new x;
now D06P2 guard Y is new y;
decide no;
decide yes;
To complete the D06P2 calculation:
[the encoding of D06P2 blocks means we don't need to sort it]
let i be 0;
while taking a D06P2 guard step is not the last:
[show the D06P2 grid;
say "[paragraph break]";
read raw input;]
log "i = [i]" at INFO every 100 of i;
increment i;
sort D06P2 obstructions;
let result be the distinct count of already-sorted D06P2 obstructions;
say "[result][line break]";
now D06P2 blocks by row is {};
now D06P2 blocks by column is {};
now D06P2 obstructions is {};
now D06P2 visited is {};
now D06P2 visited buffer is {};
disable raw input;
unpush D06P2 button;
[
D06P2 begins when play begins.
When D06P2 ends:
end the story.
Test example with "....#..... / .........# / .......... / ..#....... / .......#.. / .......... / .#..^..... / ........#. / #......... / ......#... / /"
]
Chapter - Day 07
Day 7 is a room.
d7 is a direction. d7 has opposite outside. Index map with d7 mapped as inside.
Door 7 is a door. Door 7 is d7 of the Vortex and outside of Day 7.
Section - Part 1
D07P1 button is a part 1 button.
D07P1 button is here.
D07P1 scene is a recurring scene.
D07P1 scene begins when D07P1 button is switched on.
D07P1 scene ends when D07P1 button is switched off.
Table of Stars (continued)
Day Part Button
7 1 D07P1 button
The D07P1 result is a list of number that varies.
When D07P1 scene begins:
now D07P1 result is BIGNUM_ZERO;
enable raw input;
After reading a raw input when D07P1 scene is happening:
if raw input is "":
complete the D07P1 calculation;
else:
read a D07P1 line;
To decide if (initial target - list of number) is a D07P1 possibility for (coefficients - list of list of numbers):
[(target..., coefficients i), ...]
let todo be a list of list of numbers;
let entry be a list of numbers;
add initial target to entry;
add the number of entries in coefficients to entry;
add entry to todo;
let seen be a list of list of list of numbers;
repeat with coefficient running through coefficients:
let seen entries be a list of list of numbers;
add seen entries to seen;
while todo is not empty:
let todo n be the number of entries in todo;
let target be entry todo n in todo;
let target n be the number of entries in target;
let coefficient i be entry target n in target;
truncate target to target n - 1 entries;
truncate todo to todo n - 1 entries;
if coefficient i is 1:
if target is entry 1 in coefficients:
decide yes;
next;
if target is listed in entry coefficient i in seen:
next;
add target to entry coefficient i in seen;
let coefficient be entry coefficient i in coefficients;
log "target=[target in bignum notation] coefficient=[coefficient in bignum notation]" at INFO;
[We have no negative numbers]
if target is bignum at least coefficient:
log " [target in brace notation] - [coefficient in brace notation]" at INFO;
let addition entry be target bignum- coefficient;
add coefficient i - 1 to addition entry;
add addition entry to todo;
if coefficient is BIGNUM_ZERO:
if target is BIGNUM_ZERO:
log " [target] / [coefficient] (0)" at INFO;
let division entry be BIGNUM_ZERO;
add coefficient i - 1 to division entry;
add division entry to todo;
else:
log " [target] / [coefficient]" at INFO;
let division target be target bignum/ coefficient;
let divisibility check be division target bignum* coefficient;
if divisibility check is target:
add coefficient i - 1 to division target;
add division target to todo;
decide no;
To read a D07P1 line:
let w be the words of raw input;
replace the text ":" in entry 1 in w with "";
let target be entry 1 in w converted to bignum;
let coefficients be a list of list of numbers;
repeat with i running from 2 to the number of entries in w:
let n be entry i in w converted to bignum;
add n to coefficients;
log "[target in bignum notation]: [coefficients in brace notation]" at INFO;
if target is a D07P1 possibility for coefficients:
now D07P1 result is D07P1 result bignum+ target;
say "Y[line break]";
else:
say "N[line break]";
To complete the D07P1 calculation:
say "[D07P1 result in bignum notation][line break]";
disable raw input;
unpush D07P1 button;
Section - Part 2
D07P2 button is a part 2 button.
D07P2 button is here.
D07P2 scene is a recurring scene.
D07P2 scene begins when D07P2 button is switched on.
D07P2 scene ends when D07P2 button is switched off.
Table of Stars (continued)
Day Part Button
7 2 D07P2 button
The D07P2 result is a list of number that varies.
When D07P2 scene begins:
now D07P2 result is BIGNUM_ZERO;
enable raw input;
After reading a raw input when D07P2 scene is happening:
if raw input is "":
complete the D07P2 calculation;
else:
read a D07P2 line;
To decide if (initial target - list of number) is a D07P2 possibility for (coefficients - list of list of numbers):
[(target..., coefficients i), ...]
let todo be a list of list of numbers;
let entry be a list of numbers;
add initial target to entry;
add the number of entries in coefficients to entry;
add entry to todo;
let coefficient powers be a list of list of numbers;
let seen be a list of list of list of numbers;
repeat with coefficient running through coefficients:
let power be "1";
let digit count be the number of characters in (coefficient in bignum notation);
repeat with i running from 1 to digit count:
now power is "[power]0";
add (power converted to bignum) to coefficient powers;
let seen entries be a list of list of numbers;
add seen entries to seen;
while todo is not empty:
let todo n be the number of entries in todo;
let target be entry todo n in todo;
let target n be the number of entries in target;
let coefficient i be entry target n in target;
truncate target to target n - 1 entries;
truncate todo to todo n - 1 entries;
if coefficient i is 1:
if target is entry 1 in coefficients:
decide yes;
next;
if target is listed in entry coefficient i in seen:
next;
add target to entry coefficient i in seen;
let coefficient be entry coefficient i in coefficients;
log "target=[target in bignum notation] coefficient=[coefficient in bignum notation]" at INFO;
[We have no negative numbers]
if target is bignum at least coefficient:
log " [target in brace notation] - [coefficient in brace notation]" at INFO;
let addition entry be target bignum- coefficient;
add coefficient i - 1 to addition entry;
add addition entry to todo;
if coefficient is BIGNUM_ZERO:
if target is BIGNUM_ZERO:
log " [target] / [coefficient] (0)" at INFO;
let division entry be BIGNUM_ZERO;
add coefficient i - 1 to division entry;
add division entry to todo;
else:
log " [target] / [coefficient]" at INFO;
let division target be target bignum/ coefficient;
let divisibility check be division target bignum* coefficient;
if divisibility check is target:
add coefficient i - 1 to division target;
add division target to todo;
log " [target] || [coefficient]" at INFO;
let power be entry coefficient i in coefficient powers;
let concat target be target bignum/ power;
let concat check be concat target bignum* power;
if concat check is (target bignum- coefficient):
add coefficient i - 1 to concat target;
add concat target to todo;
decide no;
To read a D07P2 line:
let w be the words of raw input;
replace the text ":" in entry 1 in w with "";
let target be entry 1 in w converted to bignum;
let coefficients be a list of list of numbers;
repeat with i running from 2 to the number of entries in w:
let n be entry i in w converted to bignum;
add n to coefficients;
log "[target in bignum notation]: [coefficients in brace notation]" at INFO;
if target is a D07P2 possibility for coefficients:
now D07P2 result is D07P2 result bignum+ target;
say "Y[line break]";
else:
say "N[line break]";
To complete the D07P2 calculation:
say "[D07P2 result in bignum notation][line break]";
disable raw input;
unpush D07P2 button;
Chapter - Day 08
Day 8 is a room.
d8 is a direction. d8 has opposite outside. Index map with d8 mapped as inside.
Door 8 is a door. Door 8 is d8 of the Vortex and outside of Day 8.
Section - Part 1
D08P1 button is a part 1 button.
D08P1 button is here.
D08P1 scene is a recurring scene.
D08P1 scene begins when D08P1 button is switched on.
D08P1 scene ends when D08P1 button is switched off.
Table of Stars (continued)
Day Part Button
8 1 D08P1 button
The D08P1 antennae is a list of list of number that varies.
The D08P1 grid width is a number that varies.
The D08P1 grid height is a number that varies.
D08P1 antennae indices is always "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
To decide what number is the D08P1 antenna index of (c - text):
if c is ".", decide on 0;
repeat with i running from 1 to the number of characters in D08P1 antennae indices:
if c is character number i in D08P1 antennae indices, decide on i;
decide on 0;
When D08P1 scene begins:
now D08P1 antennae is {};
repeat with i running from 1 to the number of characters in D08P1 antennae indices:
let x be a list of number;
add x to D08P1 antennae;
now D08P1 grid width is 0;
now D08P1 grid height is 0;
enable raw input;
After reading a raw input when D08P1 scene is happening:
if raw input is "":
complete the D08P1 calculation;
else:
read a D08P1 line;
To read a D08P1 line:
let line be raw input;
if D08P1 grid width is 0:
now D08P1 grid width is the number of characters in line;
increment D08P1 grid height;
let y be D08P1 grid height;
repeat with x running from 1 to D08P1 grid width:
let c be character number x in line;
let i be the D08P1 antenna index of c;
if i > 0:
let position be the D08P1 encoded position of x and y;
add position to entry i of D08P1 antennae;
To decide which number is the D08P1 encoded position of (x - number) and (y - number):
decide on ((y - 1) * D08P1 grid width) + x - 1;
To decide which number is the D08P1 unencoded x of (encoded position - number):
decide on (the remainder after dividing encoded position by D08P1 grid width) + 1;
To decide which number is the D08P1 unencoded y of (encoded position - number):
decide on (encoded position / D08P1 grid width) + 1;
To decide if (x - number) and (y - number) are in D08P1 grid bounds:
if 1 <= x and x <= D08P1 grid width and 1 <= y and y <= D08P1 grid height, decide yes;
decide no;
To decide which list of number is the D08P1 antinodes:
let result be a list of numbers;
repeat with antennae positions running through D08P1 antennae:
let n be the number of entries in antennae positions;
repeat with i running from 1 to n:
let ix be the D08P1 unencoded x of entry i in antennae positions;
let iy be the D08P1 unencoded y of entry i in antennae positions;
repeat with j running from i + 1 to n:
let jx be the D08P1 unencoded x of entry j in antennae positions;
let jy be the D08P1 unencoded y of entry j in antennae positions;
[say "[i]=([ix], [iy]) [j]=([jx], [jy]) ->";]
let dx be jx - ix;
let dy be jy - iy;
let ax be jx + dx;
let ay be jy + dy;
if ax and ay are in D08P1 grid bounds:
[say " ([ax], [ay])";]
add the D08P1 encoded position of ax and ay to result;
let bx be ix - dx;
let by be iy - dy;
if bx and by are in D08P1 grid bounds:
[say " ([bx], [by])";]
add the D08P1 encoded position of bx and by to result;
[say "[line break]";]
decide on result;
To complete the D08P1 calculation:
let antinodes be the D08P1 antinodes;
sort antinodes;
let result be the distinct count of already-sorted antinodes;
say "[result][line break]";
now D08P1 antennae is {};
disable raw input;
unpush D08P1 button;
[
D08P1 begins when play begins.
When D08P1 ends:
end the story.
]
Section - Part 2
D08P2 button is a part 2 button.
D08P2 button is here.
D08P2 scene is a recurring scene.
D08P2 scene begins when D08P2 button is switched on.
D08P2 scene ends when D08P2 button is switched off.
Table of Stars (continued)
Day Part Button
8 2 D08P2 button
The D08P2 antennae is a list of list of number that varies.
The D08P2 grid width is a number that varies.
The D08P2 grid height is a number that varies.
D08P2 antennae indices is always "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
To decide what number is the D08P2 antenna index of (c - text):
if c is ".", decide on 0;
repeat with i running from 1 to the number of characters in D08P2 antennae indices:
if c is character number i in D08P2 antennae indices, decide on i;
decide on 0;
When D08P2 scene begins:
now D08P2 antennae is {};
repeat with i running from 1 to the number of characters in D08P2 antennae indices:
let x be a list of number;
add x to D08P2 antennae;
now D08P2 grid width is 0;
now D08P2 grid height is 0;
enable raw input;
After reading a raw input when D08P2 scene is happening:
if raw input is "":
complete the D08P2 calculation;
else:
read a D08P2 line;
To read a D08P2 line:
let line be raw input;
if D08P2 grid width is 0:
now D08P2 grid width is the number of characters in line;
increment D08P2 grid height;
let y be D08P2 grid height;
repeat with x running from 1 to D08P2 grid width:
let c be character number x in line;
let i be the D08P2 antenna index of c;
if i > 0:
let position be the D08P2 encoded position of x and y;
add position to entry i of D08P2 antennae;
To decide which number is the D08P2 encoded position of (x - number) and (y - number):
decide on ((y - 1) * D08P2 grid width) + x - 1;
To decide which number is the D08P2 unencoded x of (encoded position - number):
decide on (the remainder after dividing encoded position by D08P2 grid width) + 1;
To decide which number is the D08P2 unencoded y of (encoded position - number):
decide on (encoded position / D08P2 grid width) + 1;
To decide if (x - number) and (y - number) are in D08P2 grid bounds:
if 1 <= x and x <= D08P2 grid width and 1 <= y and y <= D08P2 grid height, decide yes;
decide no;
To decide which list of number is the D08P2 antinodes:
let result be a list of numbers;
repeat with antennae positions running through D08P2 antennae:
let n be the number of entries in antennae positions;
repeat with i running from 1 to n:
repeat with j running from i + 1 to n:
let ix be the D08P2 unencoded x of entry i in antennae positions;
let iy be the D08P2 unencoded y of entry i in antennae positions;
let jx be the D08P2 unencoded x of entry j in antennae positions;
let jy be the D08P2 unencoded y of entry j in antennae positions;
let dx be jx - ix;
let dy be jy - iy;
while ix and iy are in D08P2 grid bounds:
add the D08P2 encoded position of ix and iy to result;
decrease ix by dx;
decrease iy by dy;
while jx and jy are in D08P2 grid bounds:
add the D08P2 encoded position of jx and jy to result;
increase jx by dx;
increase jy by dy;
decide on result;
To say the D08P2 antinodes (antinodes - list of number):
repeat with y running from 1 to D08P2 grid height:
let line be "";
repeat with x running from 1 to D08P2 grid width:
if the D08P2 encoded position of x and y is in already-sorted antinodes:
now line is "[line]#";
else:
now line is "[line].";
say "[line][line break]";
To complete the D08P2 calculation:
let antinodes be the D08P2 antinodes;
sort antinodes;
[say the D08P2 antinodes antinodes;]
let result be the distinct count of already-sorted antinodes;
say "[result][line break]";
now D08P2 antennae is {};
disable raw input;
unpush D08P2 button;
[
D08P2 begins when play begins.
When D08P2 ends:
end the story.
]
Chapter - Day 09
Day 9 is a room.
d9 is a direction. d9 has opposite outside. Index map with d9 mapped as inside.
Door 9 is a door. Door 9 is d9 of the Vortex and outside of Day 9.
Section - Part 1
D09P1 button is a part 1 button.
D09P1 button is here.
D09P1 scene is a recurring scene.
D09P1 scene begins when D09P1 button is switched on.
D09P1 scene ends when D09P1 button is switched off.
Table of Stars (continued)
Day Part Button
9 1 D09P1 button
The D09P1 disk layout is a list of numbers that varies.
When D09P1 scene begins:
now D09P1 disk layout is {};
enable raw input;
After reading a raw input when D09P1 scene is happening:
[
Trying to read digits of a very long number is _incredibly_ slow,
so instead this routine uses I6 code to parse the digits right out
of the input buffer, which works a treat.
]
let n be raw input size;
if n is even, decrement n;
let disk map be a list of numbers;
change disk map to have n entries;
repeat with i running from 1 to n:
now entry i in disk map is digit i in the raw input;
[
Now we process the input. We have two pointers, to _odd_ indices of disk map.
]
let result be BIGNUM_ZERO;
let lower map index be 1;
let upper map index be n;
let block position be 0; [The leftmost block is in position 0, such heathens.]
while lower map index < upper map index:
[We have a file at the start of the disk]
let file id be (lower map index - 1) / 2;
repeat with i running from 1 to entry lower map index in disk map:
[say "L: [file id][line break]";]
now result is result bignum+ ((file id * block position) converted to bignum);
increment block position;
[We have some empty blocks after the lower file, but we may only have one remaining file, so if that's the case, exit the loop.]
increment lower map index;
let empty blocks be entry lower map index in disk map;
increment lower map index;
if lower map index >= upper map index, break;
[If not, we have to fill empty blocks from the upper file]
now file id is (upper map index - 1) / 2;
repeat with i running from 1 to empty blocks:
decrement entry upper map index in disk map;
[say "U: [file id][line break]";]
now result is result bignum+ ((file id * block position) converted to bignum);
increment block position;
[If we exhaust the upper file, move to the next one down]
if entry upper map index in disk map is 0:
decrease upper map index by 2;
[If that leaves us with one file, we need to exit the loop]
if lower map index >= upper map index, break;
decrement file id;
let file id be (lower map index - 1) / 2;
repeat with i running from 1 to entry lower map index in disk map:
[say "E: [file id][line break]";]
now result is result bignum+ ((file id * block position) converted to bignum);
increment block position;
say "[result in bignum notation][line break]";
disable raw input;
unpush D09P1 button;
[
D09P1 begins when play begins.
When D09P1 ends:
end the story.
]
Section - Part 2
D09P2 button is a part 2 button.
D09P2 button is here.
D09P2 scene is a recurring scene.
D09P2 scene begins when D09P2 button is switched on.
D09P2 scene ends when D09P2 button is switched off.
Table of Stars (continued)
Day Part Button
9 2 D09P2 button
The D09P2 disk layout is a list of numbers that varies.
The D09P2 freeheaps is a list of list of numbers that varies.
When D09P2 scene begins:
now D09P2 disk layout is {};
now D09P2 freeheaps is {};
enable raw input;
To populate the D09P2 freeheaps from (disk map - list of numbers):
now D09P2 freeheaps is {};
repeat with i running from 1 to 9:
let span indices be a list of numbers;
add span indices to D09P2 freeheaps;
let n be the number of entries in disk map;
let i be 2;
while i <= n:
let span size be entry i in disk map;
if span size > 0:
add i to entry span size of D09P2 freeheaps;
increase i by 2;
To decide which number is the D09P2 leftmost span index in freeheaps under (file size - number):
[
We can put this file in any space >= file size, but we want to find the
leftmost, which will be the smallest of the first entry in each freeheap.
]
let result be -1;
repeat with k running from file size to 9:
if entry k of D09P2 freeheaps is not empty:
let possible index be entry 1 of entry k of D09P2 freeheaps;
if result is -1 or possible index < result:
now result is possible index;
decide on result;
To pop the first entry of (span size - number) in D09P2 freeheaps:
[Replace the first entry with the last entry]
let n be the number of entries in entry span size in D09P2 freeheaps;
let v be entry n in entry span size in D09P2 freeheaps;
now entry 1 in entry span size in D09P2 freeheaps is v;
remove entry n in entry span size in D09P2 freeheaps;
decrement n;
[Move nodes down as needed]
let i be 1;
while true is true:
let smallest index be i;
let left index be binary heap left child of i;
let right index be binary heap right child of i;
if left index <= n and entry left index in entry span size in D09P2 freeheaps < entry smallest index in entry span size in D09P2 freeheaps:
now smallest index is left index;
if right index <= n and entry right index in entry span size in D09P2 freeheaps < entry smallest index in entry span size in D09P2 freeheaps:
now smallest index is right index;
if smallest index is not i:
swap entry i and smallest index in entry span size in D09P2 freeheaps;
now i is smallest index;
else:
break;
To insert (index - number) with (span size - number) into D09P2 freeheaps:
add -1 to entry span size in D09P2 freeheaps;
let i be the number of entries in entry span size in D09P2 freeheaps;
while i > 1:
let j be the binary heap parent of i;
let parent be entry j in entry span size in D09P2 freeheaps;
if parent <= index, break;
now entry i in entry span size in D09P2 freeheaps is parent;
now i is j;
now entry i in entry span size in D09P2 freeheaps is index;
To decide what number is D09P2 move (x - list of numbers) compared to (y - list of numbers) (this is D09P2 comparator):
let xti be entry 1 of x;
let yti be entry 1 of y;
if xti < yti, decide on -1;
if xti > yti, decide on 1;
let xfi be entry 2 of x;
let yfi be entry 2 of y;
if xfi < yfi, decide on 1;
decide on -1;
After reading a raw input when D09P2 scene is happening:
[
Trying to read digits of a very long number is _incredibly_ slow,
so instead this routine uses I6 code to parse the digits right out
of the input buffer, which works a treat.
]
let n be raw input size;
if n is even, decrement n;
let disk map be a list of numbers;
change disk map to have n entries;
repeat with i running from 1 to n:
now entry i in disk map is digit i in the raw input;
[log "DM: [disk map in brace notation]" at INFO;]
populate the D09P2 freeheaps from disk map;
[
We're going to record which blocks we're going to be moving with:
moves = [(target index, file id, file size), ...]
sorted by (target index ASC, file id DESC) so they're in the correct
on-disk order.
]
let moves be a list of list of numbers;
let i be n;
let highest unmoved be -1;
while i >= 1:
let file size be entry i of disk map;
let file id be (i - 1) / 2;
let new index be the D09P2 leftmost span index in freeheaps under file size;
if new index > i:
now new index is -1;
log "M [i]/[file id] ([file size]) => [new index]" at INFO every 100 of file id;
if new index is not -1:
[Record the move]
let move be a list of number;
add new index to move;
add file id to move;
add file size to move;
add move to moves;
[Note the disk map now has free space]
now entry i in disk map is 0 - file size;
[
Now we need to decrease the size of the free span we just moved to.
We first remove it from the freeheap, but we need to figure out which one that was.
]
let free span size be entry new index of disk map;
pop the first entry of free span size in D09P2 freeheaps;
decrease free span size by file size;
[Update the disk map with the new size]
now entry new index of disk map is free span size;
if free span size > 0:
insert new index with free span size into D09P2 freeheaps;
else if highest unmoved is -1:
now highest unmoved is i;
decrease i by 2;
log "HU: [highest unmoved]" at INFO;
log "UM: [number of entries in moves]" at INFO;
sort moves by D09P2 comparator;
let highest moved be entry 1 in the last entry of moves;
log "HM: [highest moved]" at INFO;
now n is highest unmoved;
if highest moved > n:
now n is highest moved;
truncate disk map to n entries;
[log "SM: [moves in brace notation]" at INFO;]
[
Now we compute the result.
]
let result be BIGNUM_ZERO;
let map index be 1;
let move index be 1;
let block position be 0; [The leftmost block is in position 0, such heathens.]
while map index <= n:
log "[map index]/[move index]/[block position]" at INFO every 100 of map index;
if map index is odd:
[We may have an unmoved file]
let file id be (map index - 1) / 2;
let file size be entry map index of disk map;
if file size > 0:
log "F: [file id]*[file size]" at INFO;
repeat with k running from 1 to file size:
now result is result bignum+ ((file id * block position) converted to bignum);
increment block position;
else:
let free space be 0 - file size;
log "U: [free space]" at INFO;
increase block position by free space;
else:
[Record any moves which got put at this free space]
while (move index <= number of entries in moves) and (entry 1 of entry move index of moves is map index):
log "M: [entry move index of moves in brace notation]" at INFO;
let file id be entry 2 of entry move index of moves;
let file size be entry 3 of entry move index of moves;
log "F: [file id]*[file size]" at INFO;
repeat with k running from 1 to file size:
now result is result bignum+ ((file id * block position) converted to bignum);
increment block position;
increment move index;
[Then note any free space left over]
let free space be entry map index of disk map;
if free space > 0:
log "U: [free space]" at INFO;
increase block position by free space;
increment map index;
say "[result in bignum notation][line break]";
disable raw input;
unpush D09P2 button;
[
D09P2 begins when play begins.
When D09P2 ends:
end the story.
]
Chapter - Day 10
Day 10 is a room.
d10 is a direction. d10 has opposite outside. Index map with d10 mapped as inside.
Door 10 is a door. Door 10 is d10 of the Vortex and outside of Day 10.
Section - Part 1
D10P1 button is a part 1 button.
D10P1 button is here.
D10P1 scene is a recurring scene.
D10P1 scene begins when D10P1 button is switched on.
D10P1 scene ends when D10P1 button is switched off.
Table of Stars (continued)
Day Part Button
10 1 D10P1 button
The D10P1 grid is a list of list of number that varies.
The D10P1 grid width is a number that varies.
The D10P1 grid height is a number that varies.
The D10P1 zeroes is a list of number that varies.
To decide which number is the D10P1 encoded position of (x - number) and (y - number):
decide on ((y - 1) * D10P1 grid width) + x - 1;
To decide which number is the D10P1 unencoded x of (encoded position - number):
decide on (the remainder after dividing encoded position by D10P1 grid width) + 1;
To decide which number is the D10P1 unencoded y of (encoded position - number):
decide on (encoded position / D10P1 grid width) + 1;
To decide which number is the D10P1 level of (x - number) and (y - number):
decide on entry x of entry y of D10P1 grid;
When D10P1 scene begins:
now D10P1 grid is {};
now D10P1 grid width is 0;
now D10P1 grid height is 0;
Entering a D10P1 line is an action applying to one topic.
Understand "[text]" as entering a D10P1 line when D10P1 scene is happening.
Carry out entering a D10P1 line:
let line be the topic understood;
let row be a list of numbers;
if D10P1 grid width is 0:
now D10P1 grid width is the number of characters in line;
increment D10P1 grid height;
let y be D10P1 grid height;
repeat with x running from 1 to the number of characters in line:
let n be the digit value of character number x in line;
add n to row;
if n is 0:
add the D10P1 encoded position of x and y to the D10P1 zeroes;
add row to D10P1 grid;
To decide which number is the D10P1 trailhead score of (start - number):
let level be 0;
let current level be a list of numbers;
let next level be a list of number;
add start to next level;
while next level is not empty:
if level is 9, decide on the number of entries in next level;
now current level is next level;
now next level is {};
increment level;
repeat with idx running through current level:
let x be the D10P1 unencoded x of idx;
let y be the D10P1 unencoded y of idx;
if x < D10P1 grid width and D10P1 level of x + 1 and y is level:
now idx is the D10P1 encoded position of x + 1 and y;
if idx is not listed in next level, add idx to next level;
if x > 1 and D10P1 level of x - 1 and y is level:
now idx is the D10P1 encoded position of x - 1 and y;
if idx is not listed in next level, add idx to next level;
if y < D10P1 grid height and D10P1 level of x and y + 1 is level:
now idx is the D10P1 encoded position of x and y + 1;
if idx is not listed in next level, add idx to next level;
if y > 1 and D10P1 level of x and y - 1 is level:
now idx is the D10P1 encoded position of x and y - 1;
if idx is not listed in next level, add idx to next level;
log "[level]: [next level]" at INFO;
decide on 0;
To complete the D10P1 calculation:
let result be 0;
repeat with idx running through D10P1 zeroes:
let score be the D10P1 trailhead score of idx;
log "=> [score]" at INFO;
increase result by score;
say "[result][line break]";
unpush D10P1 button;
Before entering a blank line:
if D10P1 scene is happening, complete the D10P1 calculation;
[
D10P1 begins when play begins.
When D10P1 ends:
end the story.
]
Section - Part 2
D10P2 button is a part 2 button.
D10P2 button is here.
D10P2 scene is a recurring scene.
D10P2 scene begins when D10P2 button is switched on.
D10P2 scene ends when D10P2 button is switched off.
Table of Stars (continued)
Day Part Button
10 2 D10P2 button
The D10P2 grid is a list of list of number that varies.
The D10P2 grid width is a number that varies.
The D10P2 grid height is a number that varies.
The D10P2 index is a list of list of number that varies.
To decide which number is the D10P2 encoded position of (x - number) and (y - number):
decide on ((y - 1) * D10P2 grid width) + x;
To decide which number is the D10P2 unencoded x of (encoded position - number):
decide on (the remainder after dividing (encoded position - 1) by D10P2 grid width) + 1;
To decide which number is the D10P2 unencoded y of (encoded position - number):
decide on ((encoded position - 1) / D10P2 grid width) + 1;
To decide which number is the D10P2 level of (x - number) and (y - number):
decide on entry x of entry y of D10P2 grid;
When D10P2 scene begins:
now D10P2 grid is {};
now D10P2 grid width is 0;
now D10P2 grid height is 0;
now D10P2 index is {};
repeat with k running from 0 to 9:
let index row be a list of number;
add index row to D10P2 index;
Entering a D10P2 line is an action applying to one topic.
Understand "[text]" as entering a D10P2 line when D10P2 scene is happening.
Carry out entering a D10P2 line:
let line be the topic understood;
let row be a list of numbers;
if D10P2 grid width is 0:
now D10P2 grid width is the number of characters in line;
increment D10P2 grid height;
let y be D10P2 grid height;
repeat with x running from 1 to the number of characters in line:
let n be the digit value of character number x in line;
add n to row;
let idx be the D10P2 encoded position of x and y;
add idx to entry n + 1 of D10P2 index;
add row to D10P2 grid;
To decide which list of number is the D10P2 precomputed ratings:
let WH be D10P2 grid width * D10P2 grid height;
let previous flatgrid be a list of number;
repeat with idx running from 1 to WH:
add 0 to previous flatgrid;
[Mark all trail ends as having 1 path]
repeat with idx running through entry 10 of D10P2 index:
now entry idx in previous flatgrid is 1;
log "[previous flatgrid in brace notation]" at INFO;
let level be 9;
while level > 0:
let flatgrid be a list of number;
repeat with idx running from 1 to WH:
add 0 to flatgrid;
repeat with idx running through entry level of D10P2 index:
let x be the D10P2 unencoded x of idx;
let y be the D10P2 unencoded y of idx;
if x > 1:
increase entry idx of flatgrid by entry D10P2 encoded position of (x - 1) and y in previous flatgrid;
if x < D10P2 grid width:
increase entry idx of flatgrid by entry D10P2 encoded position of (x + 1) and y in previous flatgrid;
if y > 1:
increase entry idx of flatgrid by entry D10P2 encoded position of x and (y - 1) in previous flatgrid;
if y < D10P2 grid height:
increase entry idx of flatgrid by entry D10P2 encoded position of x and (y + 1) in previous flatgrid;
now previous flatgrid is flatgrid;
log "[flatgrid in brace notation]" at INFO;
decrement level;
decide on previous flatgrid;
To complete the D10P2 calculation:
let result be 0;
let grid be the D10P2 precomputed ratings;
repeat with idx running through entry 1 of D10P2 index:
let score be entry idx in grid;
log "=> [score]" at INFO;
increase result by score;
say "[result][line break]";
unpush D10P2 button;
Before entering a blank line:
if D10P2 scene is happening, complete the D10P2 calculation;
[
D10P2 begins when play begins.
When D10P2 ends:
end the story.
]
Chapter - Day 11
Day 11 is a room.
d11 is a direction. d11 has opposite outside. Index map with d11 mapped as inside.
Door 11 is a door. Door 11 is d11 of the Vortex and outside of Day 11.
Section - Part 1
D11P1 button is a part 1 button.
D11P1 button is here.
D11P1 scene is a recurring scene.
D11P1 scene begins when D11P1 button is switched on.
D11P1 scene ends when D11P1 button is switched off.
Table of Stars (continued)
Day Part Button
11 1 D11P1 button
To decide what text is the D11P1 remove leading zeroes of (x - text):
let n be the number of characters in x;
let i be 1;
while i < n:
if character number i in x is not "0", break;
increment i;
decide on the substring of x from i to n;
D11P1_HASH_BUCKETS is always 4096.
[
We have two mappings A and B which are both {N: count}, and each blink, we switch between them.
To make things easy, these share keys.
]
D11P1 keys is a list of text that varies.
D11P1 keys index is a list of list of numbers that varies.
D11P1 successors is a list of list of numbers that varies.
D11P1 A counts is a list of list of number that varies.
D11P1 B counts is a list of list of number that varies.
To decide what number is the D11P1 hash value of (x - text):
let h be 0;
let n be the number of characters in x;
repeat with i running from 1 to n:
now h is (h * 31) + (the ordinal of character number i in x);
decide on h;
To decide what number is the D11P1 bucket index of (x - text):
let h be the D11P1 hash value of x;
let i be the remainder after dividing h by D11P1_HASH_BUCKETS;
if i < 0:
increase i by D11P1_HASH_BUCKETS;
if i < 0 or i >= D11P1_HASH_BUCKETS:
log "FAILED TO CORRECT MOD: [x] -> [i]" at ERROR;
decide on i + 1;
To decide what number is the maybe-inserted D11P1 key index of (pebble - text):
let i be the D11P1 bucket index of pebble;
let j be 1;
let n be the number of entries in entry i in D11P1 keys index;
while j <= n:
let key index be entry j in entry i in D11P1 keys index;
if entry key index in D11P1 keys is pebble:
decide on key index;
increment j;
add pebble to D11P1 keys;
let successors be a list of numbers;
add successors to D11P1 successors;
let key index be the number of entries in D11P1 keys;
add BIGNUM_ZERO to D11P1 A counts;
add BIGNUM_ZERO to D11P1 B counts;
add key index to entry i in D11P1 keys index;
decide on key index;
To increase D11P1 pebble count for (pebble - text) by (count - list of number) on (turn - number):
let k be the maybe-inserted D11P1 key index of pebble;
if turn is even:
now entry k in D11P1 A counts is entry k in D11P1 A counts bignum+ count;
else:
now entry k in D11P1 B counts is entry k in D11P1 B counts bignum+ count;
To process a D11P1 blink on (turn - number):
let n be the number of entries in D11P1 keys;
repeat with i running from 1 to n:
let count be a list of numbers;
if turn is even:
now count is entry i in D11P1 B counts;
else:
now count is entry i in D11P1 A counts;
if count is BIGNUM_ZERO, next;
let successors be entry i in D11P1 successors;
if successors is empty:
let p be entry i in D11P1 keys;
if p is "0":
add the maybe-inserted D11P1 key index of "1" to successors;
else:
let digit count be the number of characters in p;
if digit count is even:
let left be the substring of p from 1 to digit count / 2;
add the maybe-inserted D11P1 key index of left to successors;
let j be (digit count / 2) + 1;
while j < digit count and character number j in p is "0":
increment j;
let right be the substring of p from j to digit count;
add the maybe-inserted D11P1 key index of right to successors;
else:
let pn be (p converted to bignum) bignum* BIGNUM_2024;
add the maybe-inserted D11P1 key index of (pn in bignum notation) to successors;
now entry i in D11P1 successors is successors;
[log "S: [p] -> [successors in brace notation]" at INFO;]
repeat with j running through successors:
if turn is even:
now entry j in D11P1 A counts is entry j in D11P1 A counts bignum+ count;
else:
now entry j in D11P1 B counts is entry j in D11P1 B counts bignum+ count;
now n is the number of entries in D11P1 keys;
repeat with i running from 1 to n:
if turn is even:
now entry i in D11P1 B counts is BIGNUM_ZERO;
else:
now entry i in D11P1 A counts is BIGNUM_ZERO;
To decide which text is the D11P1 result of (t - text) with (n - number) steps:
now D11P1 keys is {};
now D11P1 keys index is {};
repeat with i running from 1 to D11P1_HASH_BUCKETS:
let bucket be a list of numbers;
add bucket to D11P1 keys index;
now D11P1 A counts is {};
now D11P1 B counts is {};
repeat with p running through the words of t:
increase D11P1 pebble count for p by BIGNUM_ONE on 0;
repeat with turn running from 1 to n:
process a D11P1 blink on turn;
log "After [turn] blinks: [number of entries in D11P1 keys] distinct pebble numbers" at WARNING;
let result be BIGNUM_ZERO;
repeat with count running through D11P1 B counts:
now result is result bignum+ count;
now D11P1 keys is {};
now D11P1 keys index is {};
now D11P1 A counts is {};
now D11P1 B counts is {};
decide on result in bignum notation;
Entering a D11P1 line is an action applying to one topic.
Understand "[text]" as entering a D11P1 line when D11P1 scene is happening.
Carry out entering a D11P1 line:
let result be D11P1 result of the topic understood with 25 steps;
say "[result][line break]";
unpush D11P1 button;
Section - Part 2
D11P2 button is a part 2 button.
D11P2 button is here.
D11P2 scene is a recurring scene.
D11P2 scene begins when D11P2 button is switched on.
D11P2 scene ends when D11P2 button is switched off.
Table of Stars (continued)
Day Part Button
11 2 D11P2 button
Entering a D11P2 line is an action applying to one topic.
Understand "[text]" as entering a D11P2 line when D11P2 scene is happening.
Carry out entering a D11P2 line:
let result be D11P1 result of the topic understood with 75 steps;
say "[result][line break]";
unpush D11P2 button;
Chapter - Day 12
Day 12 is a room.
d12 is a direction. d12 has opposite outside. Index map with d12 mapped as inside.
Door 12 is a door. Door 12 is d12 of the Vortex and outside of Day 12.
Section - Part 1
D12P1 button is a part 1 button.
D12P1 button is here.
D12P1 scene is a recurring scene.
D12P1 scene begins when D12P1 button is switched on.
D12P1 scene ends when D12P1 button is switched off.
Table of Stars (continued)
Day Part Button
12 1 D12P1 button
The D12P1 grid is a list of text that varies.
The D12P1 grid width is a number that varies.
The D12P1 grid height is a number that varies.
When D12P1 scene begins:
now D12P1 grid is {};
now D12P1 grid width is 0;
now D12P1 grid height is 0;
Entering a D12P1 line is an action applying to one topic.
Understand "[text]" as entering a D12P1 line when D12P1 scene is happening.
Carry out entering a D12P1 line:
let line be the topic understood;
if D12P1 grid width is 0:
now D12P1 grid width is the number of characters in line;
increment D12P1 grid height;
add line to D12P1 grid;
To decide which number is the D12P1 encoded position of (x - number) and (y - number):
decide on ((y - 1) * D12P1 grid width) + x;
To decide which number is the D12P1 unencoded x of (encoded position - number):
decide on (the remainder after dividing (encoded position - 1) by D12P1 grid width) + 1;
To decide which number is the D12P1 unencoded y of (encoded position - number):
decide on ((encoded position - 1) / D12P1 grid width) + 1;
To decide which text is the D12P1 plant at (x - number) and (y - number):
decide on character number x in entry y in D12P1 grid;
To remove D12P1 plant at (x - number) and (y - number):
replace character number x in entry y in D12P1 grid with "-";
To decide which list of numbers is the D12P1 region at (x - number) and (y - number):
let start be the D12P1 encoded position of x and y;
let plant be the D12P1 plant at x and y;
remove D12P1 plant at x and y;
let seen be a list of numbers;
let todo be a list of numbers;
add start to todo;
while todo is not empty:
let n be the number of entries in todo;
let idx be entry n in todo;
truncate todo to n - 1 entries;
add idx to seen;
now x is the D12P1 unencoded x of idx;
now y is the D12P1 unencoded y of idx;
if x > 1 and D12P1 plant at x - 1 and y is plant:
now idx is the D12P1 encoded position of x - 1 and y;
add idx to todo;
remove D12P1 plant at x - 1 and y;
if x < D12P1 grid width and D12P1 plant at x + 1 and y is plant:
now idx is the D12P1 encoded position of x + 1 and y;
add idx to todo;
remove D12P1 plant at x + 1 and y;
if y > 1 and D12P1 plant at x and y - 1 is plant:
now idx is the D12P1 encoded position of x and y - 1;
add idx to todo;
remove D12P1 plant at x and y - 1;
if y < D12P1 grid height and D12P1 plant at x and y + 1 is plant:
now idx is the D12P1 encoded position of x and y + 1;
add idx to todo;
remove D12P1 plant at x and y + 1;
decide on seen;
To decide which number is the D12P1 perimeter of (r - list of numbers):
sort r;
let result be 0;
repeat with idx running through r:
let x be the D12P1 unencoded x of idx;
let y be the D12P1 unencoded y of idx;
if (x is 1) or (D12P1 encoded position of x - 1 and y) is not in already-sorted r:
increment result;
if (x is D12P1 grid width) or (D12P1 encoded position of x + 1 and y) is not in already-sorted r:
increment result;
if (y is 1) or (D12P1 encoded position of x and y - 1) is not in already-sorted r:
increment result;
if (y is D12P1 grid height) or (D12P1 encoded position of x and y + 1) is not in already-sorted r:
increment result;
decide on result;
To complete the D12P1 calculation:
let result be 0;
let x be 1;
let y be 1;
while y <= D12P1 grid height:
let p be D12P1 plant at x and y;
log "[x],[y] = [p]" at INFO;
if p is not "-":
let r be the D12P1 region at x and y;
log "R: [r]" at INFO;
let area be number of entries in r;
let perimeter be D12P1 perimeter of r;
increase result by area * perimeter;
log "=> [area]x[perimeter] -> [result]" at WARNING;
increment x;
if x > D12P1 grid width:
now x is 1;
increment y;
say "[result][line break]";
unpush D12P1 button;
Before entering a blank line:
if D12P1 scene is happening, complete the D12P1 calculation;
[
D12P1 begins when play begins.
When D12P1 ends:
end the story.
]
Section - Part 2
D12P2 button is a part 2 button.
D12P2 button is here.
D12P2 scene is a recurring scene.
D12P2 scene begins when D12P2 button is switched on.
D12P2 scene ends when D12P2 button is switched off.
Table of Stars (continued)
Day Part Button
12 2 D12P2 button
The D12P2 grid is a list of text that varies.
The D12P2 grid width is a number that varies.
The D12P2 grid height is a number that varies.
When D12P2 scene begins:
now D12P2 grid is {};
now D12P2 grid width is 0;
now D12P2 grid height is 0;
Entering a D12P2 line is an action applying to one topic.
Understand "[text]" as entering a D12P2 line when D12P2 scene is happening.
Carry out entering a D12P2 line:
let line be the topic understood;
if D12P2 grid width is 0:
now D12P2 grid width is the number of characters in line;
increment D12P2 grid height;
add line to D12P2 grid;
To decide which number is the D12P2 encoded position of (x - number) and (y - number):
decide on ((y - 1) * D12P2 grid width) + x;
To decide which number is the D12P2 unencoded x of (encoded position - number):
decide on (the remainder after dividing (encoded position - 1) by D12P2 grid width) + 1;
To decide which number is the D12P2 unencoded y of (encoded position - number):
decide on ((encoded position - 1) / D12P2 grid width) + 1;
To decide which text is the D12P2 plant at (x - number) and (y - number):
decide on character number x in entry y in D12P2 grid;
To remove D12P2 plant at (x - number) and (y - number):
replace character number x in entry y in D12P2 grid with "-";
To decide which list of numbers is the D12P2 region at (x - number) and (y - number):
let start be the D12P2 encoded position of x and y;
let plant be the D12P2 plant at x and y;
remove D12P2 plant at x and y;
let seen be a list of numbers;
let todo be a list of numbers;
add start to todo;
while todo is not empty:
let n be the number of entries in todo;
let idx be entry n in todo;
truncate todo to n - 1 entries;
add idx to seen;
now x is the D12P2 unencoded x of idx;
now y is the D12P2 unencoded y of idx;
if x > 1 and D12P2 plant at x - 1 and y is plant:
now idx is the D12P2 encoded position of x - 1 and y;
add idx to todo;
remove D12P2 plant at x - 1 and y;
if x < D12P2 grid width and D12P2 plant at x + 1 and y is plant:
now idx is the D12P2 encoded position of x + 1 and y;
add idx to todo;
remove D12P2 plant at x + 1 and y;
if y > 1 and D12P2 plant at x and y - 1 is plant:
now idx is the D12P2 encoded position of x and y - 1;
add idx to todo;
remove D12P2 plant at x and y - 1;
if y < D12P2 grid height and D12P2 plant at x and y + 1 is plant:
now idx is the D12P2 encoded position of x and y + 1;
add idx to todo;
remove D12P2 plant at x and y + 1;
decide on seen;
To decide which number is the D12P2 encoded pose of (encoded position - number) and (orientation - number):
decide on (encoded position * 4) + orientation;
To decide which number is the D12P2 unencoded position of (encoded pose - number):
decide on encoded pose / 4;
To decide which number is the D12P2 unencoded orientation of (encoded pose - number):
decide on the remainder after dividing encoded pose by 4;
[These apply to both poses and orientations.]
Definition: a number is D12P2 horizontal if it is even;
Definition: a number is D12P2 vertical if it is odd;
To decide which list of number is the D12P2 perimeter of (r - list of numbers):
sort r;
let result be a list of number;
repeat with idx running through r:
let x be the D12P2 unencoded x of idx;
let y be the D12P2 unencoded y of idx;
if (x is 1) or (D12P2 encoded position of x - 1 and y) is not in already-sorted r:
add the D12P2 encoded pose of idx and 0 to result;
if (y is 1) or (D12P2 encoded position of x and y - 1) is not in already-sorted r:
add the D12P2 encoded pose of idx and 1 to result;
if (x is D12P2 grid width) or (D12P2 encoded position of x + 1 and y) is not in already-sorted r:
add the D12P2 encoded pose of idx and 2 to result;
if (y is D12P2 grid height) or (D12P2 encoded position of x and y + 1) is not in already-sorted r:
add the D12P2 encoded pose of idx and 3 to result;
[by the pose encoding and the insertion order above, result is already sorted]
decide on result;
To decide which number is the D12P2 sides of (perimeter - list of numbers):
let result be 0;
while perimeter is not empty:
[We have a side]
increment result;
[Remove all adjacent parts of the perimeter]
let pose be entry 1 in perimeter;
let position be the D12P2 unencoded position of pose;
let x be the D12P2 unencoded x of position;
let y be the D12P2 unencoded y of position;
let orientation be the D12P2 unencoded orientation of pose;
log "p ([x],[y],[orientation])" at INFO;
let consumed be a list of numbers;
add pose to consumed;
if orientation is D12P2 vertical:
[Look left]
let nx be x - 1;
while nx >= 1:
let idx be the D12P2 encoded pose of (D12P2 encoded position of nx and y) and orientation;
if idx is in already-sorted perimeter:
add idx to consumed;
decrement nx;
else:
break;
[Look right]
now nx is x + 1;
while nx <= D12P2 grid width:
let idx be the D12P2 encoded pose of (D12P2 encoded position of nx and y) and orientation;
if idx is in already-sorted perimeter:
add idx to consumed;
increment nx;
else:
break;
else:
[Look up]
let ny be y - 1;
while ny >= 1:
let idx be the D12P2 encoded pose of (D12P2 encoded position of x and ny) and orientation;
if idx is in already-sorted perimeter:
add idx to consumed;
decrement ny;
else:
break;
[Look down]
now ny is y + 1;
while ny <= D12P2 grid height:
let idx be the D12P2 encoded pose of (D12P2 encoded position of x and ny) and orientation;
if idx is in already-sorted perimeter:
add idx to consumed;
increment ny;
else:
break;
[Now remove all the parts of the side we found]
sort consumed;
log "-> [consumed]" at INFO;
let new be a list of numbers;
let i be 1;
let n be the number of entries in consumed;
repeat with idx running through perimeter:
if i <= n and idx is entry i in consumed:
increment i;
else:
add idx to new;
now perimeter is new;
log "=> [perimeter]" at INFO;
decide on result;
To complete the D12P2 calculation:
let result be 0;
let x be 1;
let y be 1;
while y <= D12P2 grid height:
let p be D12P2 plant at x and y;
log "[x],[y] = [p]" at INFO;
if p is not "-":
let r be the D12P2 region at x and y;
log "R: [r]" at INFO;
let area be number of entries in r;
let perimeter be D12P2 perimeter of r;
log "P: [perimeter]" at INFO;
let sides be D12P2 sides of perimeter;
if sides is 0, break;
increase result by area * sides;
log "=> [area]x[sides] -> [result]" at WARNING;
increment x;
if x > D12P2 grid width:
now x is 1;
increment y;
say "[result][line break]";
unpush D12P2 button;
Before entering a blank line:
if D12P2 scene is happening, complete the D12P2 calculation;
[
D12P2 begins when play begins.
When D12P2 ends:
end the story.
]
Chapter - Day 13
Day 13 is a room.
d13 is a direction. d13 has opposite outside. Index map with d13 mapped as inside.
Door 13 is a door. Door 13 is d13 of the Vortex and outside of Day 13.
Section - Part 1
D13P1 button is a part 1 button.
D13P1 button is here.
D13P1 scene is a recurring scene.
D13P1 scene begins when D13P1 button is switched on.
D13P1 scene ends when D13P1 button is switched off.
Table of Stars (continued)
Day Part Button
13 1 D13P1 button
The D13P1 AX is a number that varies.
The D13P1 AY is a number that varies.
The D13P1 BX is a number that varies.
The D13P1 BY is a number that varies.
The D13P1 PX is a number that varies.
The D13P1 PY is a number that varies.
The D13P1 pending is a truth state that varies.
The D13P1 result is a number that varies.
When D13P1 scene begins:
now D13P1 pending is false;
now D13P1 result is 0;
enable punctuation stripping;
Entering a D13P1 line is an action applying to one topic.
Understand "button [text]" as entering a D13P1 line when D13P1 scene is happening.
Understand "button [text]" as entering a D13P1 line when D13P1 scene is happening.
Understand "prize [text]" as entering a D13P1 line when D13P1 scene is happening.
Carry out entering a D13P1 line:
let words be the words of the topic understood;
if entry 1 in words exactly matches the text "a", case insensitively:
now D13P1 AX is the suffix of entry 2 in words from 3 understood as a number;
now D13P1 AY is the suffix of entry 3 in words from 3 understood as a number;
else if entry 1 in words exactly matches the text "b", case insensitively:
now D13P1 BX is the suffix of entry 2 in words from 3 understood as a number;
now D13P1 BY is the suffix of entry 3 in words from 3 understood as a number;
else:
now D13P1 PX is the suffix of entry 1 in words from 3 understood as a number;
now D13P1 PY is the suffix of entry 2 in words from 3 understood as a number;
now D13P1 pending is true;
To decide which number is the D13P1 score of the claw machine:
log "[D13P1 AX],[D13P1 AY],[D13P1 BX],[D13P1 BY],[D13P1 PX],[D13P1 PY]" at INFO;
let bx numerator be D13P1 AY * D13P1 BX;
let f be the gcd of bx numerator and D13P1 AX;
now bx numerator is bx numerator / f;
let bx denominator be D13P1 AX / f;
let px numerator be D13P1 AY * D13P1 PX;
now f is the gcd of px numerator and D13P1 AX;
now px numerator is px numerator / f;
let px denominator be D13P1 AX / f;
log "[bx numerator]/[bx denominator] [px numerator]/[px denominator]" at INFO;
[bx = bx - by]
now bx numerator is (bx numerator) - (D13P1 BY * bx denominator);
[px = px - py]
now px numerator is (px numerator) - (D13P1 PY * px denominator);
log "[bx numerator]/[bx denominator] [px numerator]/[px denominator]" at INFO;
now px numerator is px numerator * bx denominator;
now px denominator is px denominator * bx numerator;
log "[px numerator]/[px denominator]" at INFO;
if px numerator is not divisible by px denominator:
decide on 0;
now px numerator is px numerator / px denominator;
log "B = [px numerator]" at WARNING;
if px numerator > 100:
decide on 0;
now bx numerator is D13P1 PX - (D13P1 BX * px numerator);
if bx numerator is not divisible by D13P1 AX:
decide on 0;
now bx numerator is bx numerator / D13P1 AX;
if bx numerator > 100:
decide on 0;
log "A = [bx numerator]" at WARNING;
decide on (bx numerator * 3) + px numerator;
To complete the D13P1 calculation:
say "[D13P1 result][line break]";
disable punctuation stripping;
unpush D13P1 button;
Before entering a blank line:
if D13P1 scene is happening:
if D13P1 pending is true:
increase D13P1 result by the D13P1 score of the claw machine;
now D13P1 pending is false;
else:
complete the D13P1 calculation;
[
D13P1 begins when play begins.
When D13P1 ends:
end the story.
]
Section - Part 2
D13P2 button is a part 2 button.
D13P2 button is here.
D13P2 scene is a recurring scene.
D13P2 scene begins when D13P2 button is switched on.
D13P2 scene ends when D13P2 button is switched off.
Table of Stars (continued)
Day Part Button
13 2 D13P2 button
The D13P2 AX is a number that varies.
The D13P2 AY is a number that varies.
The D13P2 BX is a number that varies.
The D13P2 BY is a number that varies.
The D13P2 PX is a number that varies.
The D13P2 PY is a number that varies.
The D13P2 pending is a truth state that varies.
The D13P2 result is a list of numbers that varies.
When D13P2 scene begins:
now D13P2 pending is false;
now D13P2 result is BIGNUM_ZERO;
enable punctuation stripping;
Entering a D13P2 line is an action applying to one topic.
Understand "button [text]" as entering a D13P2 line when D13P2 scene is happening.
Understand "button [text]" as entering a D13P2 line when D13P2 scene is happening.
Understand "prize [text]" as entering a D13P2 line when D13P2 scene is happening.
Carry out entering a D13P2 line:
let words be the words of the topic understood;
if entry 1 in words exactly matches the text "a", case insensitively:
now D13P2 AX is the suffix of entry 2 in words from 3 understood as a number;
now D13P2 AY is the suffix of entry 3 in words from 3 understood as a number;
else if entry 1 in words exactly matches the text "b", case insensitively:
now D13P2 BX is the suffix of entry 2 in words from 3 understood as a number;
now D13P2 BY is the suffix of entry 3 in words from 3 understood as a number;
else:
now D13P2 PX is the suffix of entry 1 in words from 3 understood as a number;
now D13P2 PY is the suffix of entry 2 in words from 3 understood as a number;
now D13P2 pending is true;
To decide which list of numbers is the D13P2 score of the claw machine:
let px be (D13P2 PX converted to bignum) bignum+ BIGNUM_1e13;
let py be (D13P2 PY converted to bignum) bignum+ BIGNUM_1e13;
let bx numerator be D13P2 AY * D13P2 BX;
let f be the gcd of bx numerator and D13P2 AX;
now bx numerator is bx numerator / f;
let bx denominator be D13P2 AX / f;
let px numerator be (D13P2 AY converted to bignum) bignum* px;
let px denominator be D13P2 AX;
[bx = bx - by]
now bx numerator is (bx numerator) - (D13P2 BY * bx denominator);
[px = px - py]
now px numerator is ((px numerator) bignum- (py bignum* (px denominator converted to bignum)));
now px numerator is px numerator bignum* (bx denominator converted to bignum);
now px denominator is px denominator * bx numerator;
let b be px numerator bignum/ (px denominator converted to bignum);
if (b bignum* (px denominator converted to bignum)) is not px numerator:
decide on BIGNUM_ZERO;
log "B = [b in bignum notation]" at INFO;
let foo be px bignum- ((D13P2 BX converted to bignum) bignum* b);
let ax be D13P2 AX converted to bignum;
let a be foo bignum/ ax;
if (a bignum* ax) is not foo:
decide on BIGNUM_ZERO;
log "A = [a in bignum notation]" at INFO;
decide on (a bignum* (3 converted to bignum)) bignum+ b;
To complete the D13P2 calculation:
say "[D13P2 result in bignum notation][line break]";
disable punctuation stripping;
unpush D13P2 button;
Before entering a blank line:
if D13P2 scene is happening:
if D13P2 pending is true:
now D13P2 result is D13P2 result bignum+ the D13P2 score of the claw machine;
now D13P2 pending is false;
else:
complete the D13P2 calculation;
[
D13P2 begins when play begins.
When D13P2 ends:
end the story.
]
Chapter - Day 14
Day 14 is a room.
d14 is a direction. d14 has opposite outside. Index map with d14 mapped as inside.
Door 14 is a door. Door 14 is d14 of the Vortex and outside of Day 14.
Section - Part 1
D14P1 button is a part 1 button.
D14P1 button is here.
D14P1 scene is a recurring scene.
D14P1 scene begins when D14P1 button is switched on.
D14P1 scene ends when D14P1 button is switched off.
Table of Stars (continued)
Day Part Button
14 1 D14P1 button
The D14P1 TL quadrant is a number that varies.
The D14P1 TR quadrant is a number that varies.
The D14P1 BL quadrant is a number that varies.
The D14P1 BR quadrant is a number that varies.
D14P1 steps is always 100;
[
D14P1 width is always 11.
D14P1 width divider is always 5.
D14P1 height is always 7.
D14P1 height divider is always 3.
]
D14P1 width is always 101.
D14P1 width divider is always 50.
D14P1 height is always 103.
D14P1 height divider is always 51.
When D14P1 scene begins:
now D14P1 TL quadrant is 0;
now D14P1 TR quadrant is 0;
now D14P1 BL quadrant is 0;
now D14P1 BR quadrant is 0;
enable punctuation stripping;
Entering a D14P1 line is an action applying to one topic.
Understand "[text]" as entering a D14P1 line when D14P1 scene is happening.
Carry out entering a D14P1 line:
let words be the the topic understood split by any of {" ", ",", "="};
let px be entry 2 in words understood as a number;
let py be entry 3 in words understood as a number;
let vx be entry 5 in words understood as a number;
let vy be entry 6 in words understood as a number;
log "p=([px],[py]) v=([vx],[vy])" at INFO;
while vx < 0:
increase vx by D14P1 width;
while vy < 0:
increase vy by D14P1 height;
let nx be the remainder after dividing (px + (vx * D14P1 steps)) by D14P1 width;
let ny be the remainder after dividing (py + (vy * D14P1 steps)) by D14P1 height;
log "n=([nx], [ny])" at INFO;
if nx < D14P1 width divider:
if ny < D14P1 height divider:
increment D14P1 TL quadrant;
else if ny > D14P1 height divider:
increment D14P1 BL quadrant;
else if nx > D14P1 width divider:
if ny < D14P1 height divider:
increment D14P1 TR quadrant;
else if ny > D14P1 height divider:
increment D14P1 BR quadrant;
To complete the D14P1 calculation:
log "TL: [D14P1 TL quadrant]" at INFO;
log "TR: [D14P1 TR quadrant]" at INFO;
log "BL: [D14P1 BL quadrant]" at INFO;
log "BR: [D14P1 BR quadrant]" at INFO;
let result be D14P1 TL quadrant * D14P1 TR quadrant * D14P1 BL quadrant * D14P1 BR quadrant;
say "[result][line break]";
disable punctuation stripping;
unpush D14P1 button;
Before entering a blank line:
if D14P1 scene is happening:
complete the D14P1 calculation;
[
D14P1 begins when play begins.
When D14P1 ends:
end the story.
]
Section - Part 2
D14P2 button is a part 2 button.
D14P2 button is here.
D14P2 scene is a recurring scene.
D14P2 scene begins when D14P2 button is switched on.
D14P2 scene ends when D14P2 button is switched off.
Table of Stars (continued)
Day Part Button
14 2 D14P2 button
D14P2 width is always 101.
D14P2 width divider is always 50.
D14P2 height is always 103.
D14P2 height divider is always 51.
[
You're probably wondering why there's a pile of numbers here.
Curtesy of https://github.com/jakubcerveny/gilbert, the zero-indexed
list entry (y * 101) + x maps to the index of that position on a
space-filling curve.
Our heuristic for "are there a bunch of robots together" is then to map
each robot's position to its index on this curve, sort these, and find
the length of the longest run.
]
D14P2 gilbert curve is always {
0, 1, 10, 11, 12, 13, 142, 143, 144, 145, 154, 155, 156, 159, 160, 193,
194, 197, 198, 199, 212, 213, 214, 217, 218, 2319, 2320, 2321, 2330, 2331,
2332, 2335, 2336, 2363, 2364, 2367, 2368, 2369, 2378, 2379, 2380, 2383,
2384, 2535, 2536, 2537, 2538, 2539, 2548, 2549, 2550, 2553, 2554, 2587,
2588, 2591, 2592, 2593, 2606, 2607, 2608, 2611, 2612, 3157, 3158, 3159,
3168, 3169, 3170, 3173, 3174, 3175, 3220, 3221, 3222, 3225, 3226, 3227,
3236, 3237, 3238, 3239, 3368, 3369, 3370, 3371, 3380, 3381, 3382, 3385,
3386, 3419, 3420, 3423, 3424, 3425, 3438, 3439, 3440, 3443, 3444, 3, 2, 9,
8, 15, 14, 141, 140, 147, 146, 153, 152, 157, 158, 161, 192, 195, 196, 201,
200, 211, 210, 215, 216, 219, 2318, 2323, 2322, 2329, 2328, 2333, 2334,
2337, 2362, 2365, 2366, 2371, 2370, 2377, 2376, 2381, 2382, 2385, 2534,
2533, 2532, 2541, 2540, 2547, 2546, 2551, 2552, 2555, 2586, 2589, 2590,
2595, 2594, 2605, 2604, 2609, 2610, 2613, 3156, 3161, 3160, 3167, 3166,
3171, 3172, 3177, 3176, 3219, 3218, 3223, 3224, 3229, 3228, 3235, 3234,
3241, 3240, 3367, 3366, 3373, 3372, 3379, 3378, 3383, 3384, 3387, 3418,
3421, 3422, 3427, 3426, 3437, 3436, 3441, 3442, 3445, 4, 5, 6, 7, 16, 17,
138, 139, 148, 149, 150, 151, 166, 165, 162, 191, 188, 187, 202, 205, 206,
209, 224, 223, 220, 2317, 2324, 2325, 2326, 2327, 2342, 2341, 2338, 2361,
2358, 2357, 2372, 2373, 2374, 2375, 2390, 2389, 2386, 2527, 2528, 2531,
2542, 2543, 2544, 2545, 2560, 2559, 2556, 2585, 2582, 2581, 2596, 2599,
2600, 2603, 2618, 2617, 2614, 3155, 3162, 3163, 3164, 3165, 3184, 3183,
3178, 3179, 3216, 3217, 3212, 3211, 3230, 3231, 3232, 3233, 3242, 3243,
3364, 3365, 3374, 3375, 3376, 3377, 3392, 3391, 3388, 3417, 3414, 3413,
3428, 3431, 3432, 3435, 3450, 3449, 3446, 31, 30, 29, 28, 19, 18, 137, 136,
127, 126, 125, 124, 167, 164, 163, 190, 189, 186, 203, 204, 207, 208, 225,
222, 221, 2316, 2309, 2308, 2307, 2306, 2343, 2340, 2339, 2360, 2359, 2356,
2405, 2404, 2403, 2402, 2391, 2388, 2387, 2526, 2529, 2530, 2515, 2514,
2513, 2512, 2561, 2558, 2557, 2584, 2583, 2580, 2597, 2598, 2601, 2602,
2619, 2616, 2615, 3154, 3147, 3146, 3145, 3144, 3185, 3182, 3181, 3180,
3215, 3214, 3213, 3210, 3257, 3256, 3255, 3254, 3245, 3244, 3363, 3362,
3353, 3352, 3351, 3350, 3393, 3390, 3389, 3416, 3415, 3412, 3429, 3430,
3433, 3434, 3451, 3448, 3447, 32, 33, 26, 27, 20, 21, 134, 135, 128, 129,
122, 123, 168, 169, 178, 179, 180, 185, 248, 247, 244, 243, 226, 229, 230,
2315, 2310, 2311, 2304, 2305, 2344, 2347, 2348, 2351, 2352, 2355, 2406,
2407, 2400, 2401, 2392, 2393, 2394, 2525, 2522, 2521, 2516, 2517, 2510,
2511, 2562, 2563, 2572, 2573, 2574, 2579, 2642, 2641, 2638, 2637, 2620,
2623, 2624, 3153, 3148, 3149, 3142, 3143, 3186, 3187, 3196, 3197, 3198,
3199, 3208, 3209, 3258, 3259, 3252, 3253, 3246, 3247, 3360, 3361, 3354,
3355, 3348, 3349, 3394, 3395, 3404, 3405, 3406, 3411, 3474, 3473, 3470,
3469, 3452, 3455, 3456, 35, 34, 25, 24, 23, 22, 133, 132, 131, 130, 121,
120, 171, 170, 177, 176, 181, 184, 249, 246, 245, 242, 227, 228, 231, 2314,
2313, 2312, 2303, 2302, 2345, 2346, 2349, 2350, 2353, 2354, 2409, 2408,
2399, 2398, 2397, 2396, 2395, 2524, 2523, 2520, 2519, 2518, 2509, 2508,
2565, 2564, 2571, 2570, 2575, 2578, 2643, 2640, 2639, 2636, 2621, 2622,
2625, 3152, 3151, 3150, 3141, 3140, 3189, 3188, 3195, 3194, 3201, 3200,
3207, 3206, 3261, 3260, 3251, 3250, 3249, 3248, 3359, 3358, 3357, 3356,
3347, 3346, 3397, 3396, 3403, 3402, 3407, 3410, 3475, 3472, 3471, 3468,
3453, 3454, 3457, 36, 39, 40, 73, 74, 77, 78, 81, 82, 115, 116, 119, 172,
173, 174, 175, 182, 183, 250, 251, 240, 241, 236, 235, 232, 2289, 2290,
2291, 2300, 2301, 2258, 2257, 2254, 2253, 2250, 2249, 2410, 2413, 2414,
2415, 2460, 2461, 2462, 2465, 2466, 2469, 2470, 2503, 2504, 2507, 2566,
2567, 2568, 2569, 2576, 2577, 2644, 2645, 2634, 2635, 2630, 2629, 2626,
3131, 3132, 3135, 3136, 3139, 3190, 3191, 3192, 3193, 3202, 3203, 3204,
3205, 3262, 3265, 3266, 3299, 3300, 3303, 3304, 3307, 3308, 3341, 3342,
3345, 3398, 3399, 3400, 3401, 3408, 3409, 3476, 3477, 3466, 3467, 3462,
3461, 3458, 37, 38, 41, 72, 75, 76, 79, 80, 83, 114, 117, 118, 323, 322,
315, 314, 313, 312, 253, 252, 239, 238, 237, 234, 233, 2288, 2293, 2292,
2299, 2298, 2259, 2256, 2255, 2252, 2251, 2248, 2411, 2412, 2417, 2416,
2459, 2458, 2463, 2464, 2467, 2468, 2471, 2502, 2505, 2506, 2717, 2716,
2709, 2708, 2707, 2706, 2647, 2646, 2633, 2632, 2631, 2628, 2627, 3130,
3133, 3134, 3137, 3138, 3079, 3078, 3077, 3076, 3067, 3066, 3065, 3064,
3263, 3264, 3267, 3298, 3301, 3302, 3305, 3306, 3309, 3340, 3343, 3344,
3549, 3548, 3541, 3540, 3539, 3538, 3479, 3478, 3465, 3464, 3463, 3460,
3459, 46, 45, 42, 71, 68, 67, 88, 87, 84, 113, 110, 109, 324, 321, 316,
317, 310, 311, 254, 255, 264, 265, 266, 269, 270, 2287, 2294, 2295, 2296,
2297, 2260, 2263, 2264, 2243, 2244, 2247, 2424, 2423, 2418, 2419, 2456,
2457, 2452, 2451, 2476, 2475, 2472, 2501, 2498, 2497, 2718, 2715, 2710,
2711, 2704, 2705, 2648, 2649, 2658, 2659, 2660, 2663, 2664, 3129, 3126,
3125, 3122, 3121, 3080, 3081, 3074, 3075, 3068, 3069, 3062, 3063, 3272,
3271, 3268, 3297, 3294, 3293, 3314, 3313, 3310, 3339, 3336, 3335, 3550,
3547, 3542, 3543, 3536, 3537, 3480, 3481, 3490, 3491, 3492, 3495, 3496, 47,
44, 43, 70, 69, 66, 89, 86, 85, 112, 111, 108, 325, 320, 319, 318, 309,
308, 257, 256, 263, 262, 267, 268, 271, 2286, 2279, 2278, 2277, 2276, 2261,
2262, 2265, 2242, 2245, 2246, 2425, 2422, 2421, 2420, 2455, 2454, 2453,
2450, 2477, 2474, 2473, 2500, 2499, 2496, 2719, 2714, 2713, 2712, 2703,
2702, 2651, 2650, 2657, 2656, 2661, 2662, 2665, 3128, 3127, 3124, 3123,
3120, 3083, 3082, 3073, 3072, 3071, 3070, 3061, 3060, 3273, 3270, 3269,
3296, 3295, 3292, 3315, 3312, 3311, 3338, 3337, 3334, 3551, 3546, 3545,
3544, 3535, 3534, 3483, 3482, 3489, 3488, 3493, 3494, 3497, 48, 49, 58, 59,
60, 65, 90, 91, 100, 101, 102, 107, 326, 329, 330, 303, 304, 307, 258, 259,
260, 261, 276, 275, 272, 2285, 2280, 2281, 2274, 2275, 2270, 2269, 2266,
2241, 2238, 2237, 2426, 2427, 2436, 2437, 2438, 2439, 2448, 2449, 2478,
2479, 2488, 2489, 2490, 2495, 2720, 2723, 2724, 2697, 2698, 2701, 2652,
2653, 2654, 2655, 2670, 2669, 2666, 3111, 3112, 3115, 3116, 3119, 3084,
3087, 3088, 3089, 3054, 3055, 3056, 3059, 3274, 3275, 3284, 3285, 3286,
3291, 3316, 3317, 3326, 3327, 3328, 3333, 3552, 3555, 3556, 3529, 3530,
3533, 3484, 3485, 3486, 3487, 3502, 3501, 3498, 51, 50, 57, 56, 61, 64, 93,
92, 99, 98, 103, 106, 327, 328, 331, 302, 305, 306, 291, 290, 289, 288,
277, 274, 273, 2284, 2283, 2282, 2273, 2272, 2271, 2268, 2267, 2240, 2239,
2236, 2429, 2428, 2435, 2434, 2441, 2440, 2447, 2446, 2481, 2480, 2487,
2486, 2491, 2494, 2721, 2722, 2725, 2696, 2699, 2700, 2685, 2684, 2683,
2682, 2671, 2668, 2667, 3110, 3113, 3114, 3117, 3118, 3085, 3086, 3091,
3090, 3053, 3052, 3057, 3058, 3277, 3276, 3283, 3282, 3287, 3290, 3319,
3318, 3325, 3324, 3329, 3332, 3553, 3554, 3557, 3528, 3531, 3532, 3517,
3516, 3515, 3514, 3503, 3500, 3499, 52, 53, 54, 55, 62, 63, 94, 95, 96, 97,
104, 105, 336, 335, 332, 301, 298, 297, 292, 293, 286, 287, 278, 279, 280,
2181, 2182, 2183, 2192, 2193, 2194, 2197, 2198, 2231, 2232, 2235, 2430,
2431, 2432, 2433, 2442, 2443, 2444, 2445, 2482, 2483, 2484, 2485, 2492,
2493, 2730, 2729, 2726, 2695, 2692, 2691, 2686, 2687, 2680, 2681, 2672,
2673, 2674, 3109, 3106, 3105, 3102, 3101, 3098, 3097, 3092, 3093, 3050,
3051, 3046, 3045, 3278, 3279, 3280, 3281, 3288, 3289, 3320, 3321, 3322,
3323, 3330, 3331, 3562, 3561, 3558, 3527, 3524, 3523, 3518, 3519, 3512,
3513, 3504, 3505, 3506, 589, 588, 587, 586, 585, 584, 559, 558, 557, 556,
555, 554, 337, 334, 333, 300, 299, 296, 295, 294, 285, 284, 283, 282, 281,
2180, 2185, 2184, 2191, 2190, 2195, 2196, 2199, 2230, 2233, 2234, 2013,
2012, 2011, 2010, 2009, 2008, 1987, 1986, 1985, 1984, 1967, 1966, 1965,
1964, 2731, 2728, 2727, 2694, 2693, 2690, 2689, 2688, 2679, 2678, 2677,
2676, 2675, 3108, 3107, 3104, 3103, 3100, 3099, 3096, 3095, 3094, 3049,
3048, 3047, 3044, 3815, 3814, 3813, 3812, 3811, 3810, 3785, 3784, 3783,
3782, 3781, 3780, 3563, 3560, 3559, 3526, 3525, 3522, 3521, 3520, 3511,
3510, 3509, 3508, 3507, 590, 593, 594, 579, 580, 583, 560, 563, 564, 549,
550, 553, 338, 341, 342, 369, 370, 373, 374, 375, 384, 385, 386, 389, 390,
2179, 2186, 2187, 2188, 2189, 2204, 2203, 2200, 2229, 2226, 2225, 2014,
2017, 2018, 2003, 2004, 2007, 1988, 1989, 1982, 1983, 1968, 1969, 1962,
1963, 2732, 2733, 2742, 2743, 2744, 2747, 2748, 2885, 2886, 2887, 2888,
2889, 2898, 2899, 2900, 2901, 2910, 2911, 2912, 2913, 3030, 3031, 3032,
3033, 3042, 3043, 3816, 3819, 3820, 3805, 3806, 3809, 3786, 3789, 3790,
3775, 3776, 3779, 3564, 3567, 3568, 3595, 3596, 3599, 3600, 3601, 3610,
3611, 3612, 3615, 3616, 591, 592, 595, 578, 581, 582, 561, 562, 565, 548,
551, 552, 339, 340, 343, 368, 371, 372, 377, 376, 383, 382, 387, 388, 391,
2178, 2171, 2170, 2169, 2168, 2205, 2202, 2201, 2228, 2227, 2224, 2015,
2016, 2019, 2002, 2005, 2006, 1991, 1990, 1981, 1980, 1971, 1970, 1961,
1960, 2735, 2734, 2741, 2740, 2745, 2746, 2749, 2884, 2883, 2882, 2891,
2890, 2897, 2896, 2903, 2902, 2909, 2908, 2915, 2914, 3029, 3028, 3035,
3034, 3041, 3040, 3817, 3818, 3821, 3804, 3807, 3808, 3787, 3788, 3791,
3774, 3777, 3778, 3565, 3566, 3569, 3594, 3597, 3598, 3603, 3602, 3609,
3608, 3613, 3614, 3617, 600, 599, 596, 577, 574, 573, 570, 569, 566, 547,
544, 543, 348, 347, 344, 367, 364, 363, 378, 379, 380, 381, 396, 395, 392,
2177, 2172, 2173, 2166, 2167, 2206, 2207, 2216, 2217, 2218, 2223, 2024,
2023, 2020, 2001, 1998, 1997, 1992, 1993, 1978, 1979, 1972, 1973, 1958,
1959, 2736, 2737, 2738, 2739, 2754, 2753, 2750, 2877, 2878, 2881, 2892,
2893, 2894, 2895, 2904, 2905, 2906, 2907, 2916, 2917, 3026, 3027, 3036,
3037, 3038, 3039, 3826, 3825, 3822, 3803, 3800, 3799, 3796, 3795, 3792,
3773, 3770, 3769, 3574, 3573, 3570, 3593, 3590, 3589, 3604, 3605, 3606,
3607, 3622, 3621, 3618, 601, 598, 597, 576, 575, 572, 571, 568, 567, 546,
545, 542, 349, 346, 345, 366, 365, 362, 411, 410, 409, 408, 397, 394, 393,
2176, 2175, 2174, 2165, 2164, 2209, 2208, 2215, 2214, 2219, 2222, 2025,
2022, 2021, 2000, 1999, 1996, 1995, 1994, 1977, 1976, 1975, 1974, 1957,
1956, 2769, 2768, 2767, 2766, 2755, 2752, 2751, 2876, 2879, 2880, 2865,
2864, 2863, 2862, 2931, 2930, 2929, 2928, 2919, 2918, 3025, 3024, 3015,
3014, 3013, 3012, 3827, 3824, 3823, 3802, 3801, 3798, 3797, 3794, 3793,
3772, 3771, 3768, 3575, 3572, 3571, 3592, 3591, 3588, 3637, 3636, 3635,
3634, 3623, 3620, 3619, 602, 603, 616, 617, 618, 619, 524, 525, 526, 527,
540, 541, 350, 353, 354, 357, 358, 361, 412, 413, 406, 407, 398, 399, 400,
2155, 2156, 2159, 2160, 2163, 2210, 2211, 2212, 2213, 2220, 2221, 2026,
2027, 2040, 2041, 2042, 2045, 2046, 1935, 1936, 1939, 1940, 1941, 1954,
1955, 2770, 2771, 2764, 2765, 2756, 2757, 2758, 2875, 2872, 2871, 2866,
2867, 2860, 2861, 2932, 2933, 2926, 2927, 2920, 2921, 3022, 3023, 3016,
3017, 3010, 3011, 3828, 3829, 3842, 3843, 3844, 3845, 3750, 3751, 3752,
3753, 3766, 3767, 3576, 3579, 3580, 3583, 3584, 3587, 3638, 3639, 3632,
3633, 3624, 3625, 3626, 605, 604, 615, 614, 621, 620, 523, 522, 529, 528,
539, 538, 351, 352, 355, 356, 359, 360, 415, 414, 405, 404, 403, 402, 401,
2154, 2157, 2158, 2161, 2162, 2109, 2108, 2101, 2100, 2099, 2098, 2029,
2028, 2039, 2038, 2043, 2044, 2047, 1934, 1937, 1938, 1943, 1942, 1953,
1952, 2773, 2772, 2763, 2762, 2761, 2760, 2759, 2874, 2873, 2870, 2869,
2868, 2859, 2858, 2935, 2934, 2925, 2924, 2923, 2922, 3021, 3020, 3019,
3018, 3009, 3008, 3831, 3830, 3841, 3840, 3847, 3846, 3749, 3748, 3755,
3754, 3765, 3764, 3577, 3578, 3581, 3582, 3585, 3586, 3641, 3640, 3631,
3630, 3629, 3628, 3627, 606, 609, 610, 613, 622, 623, 520, 521, 530, 533,
534, 537, 480, 479, 476, 475, 472, 471, 416, 417, 426, 427, 428, 431, 432,
2153, 2150, 2149, 2146, 2145, 2110, 2107, 2102, 2103, 2096, 2097, 2030,
2033, 2034, 2037, 2052, 2051, 2048, 1933, 1930, 1929, 1944, 1947, 1948,
1951, 2774, 2777, 2778, 2779, 2816, 2817, 2818, 2821, 2822, 2825, 2826,
2853, 2854, 2857, 2936, 2939, 2940, 2967, 2968, 2971, 2972, 2975, 2976,
3003, 3004, 3007, 3832, 3835, 3836, 3839, 3848, 3849, 3746, 3747, 3756,
3759, 3760, 3763, 3706, 3705, 3702, 3701, 3698, 3697, 3642, 3643, 3652,
3653, 3654, 3657, 3658, 607, 608, 611, 612, 625, 624, 519, 518, 531, 532,
535, 536, 481, 478, 477, 474, 473, 470, 419, 418, 425, 424, 429, 430, 433,
2152, 2151, 2148, 2147, 2144, 2111, 2106, 2105, 2104, 2095, 2094, 2031,
2032, 2035, 2036, 2053, 2050, 2049, 1932, 1931, 1928, 1945, 1946, 1949,
1950, 2775, 2776, 2781, 2780, 2815, 2814, 2819, 2820, 2823, 2824, 2827,
2852, 2855, 2856, 2937, 2938, 2941, 2966, 2969, 2970, 2973, 2974, 2977,
3002, 3005, 3006, 3833, 3834, 3837, 3838, 3851, 3850, 3745, 3744, 3757,
3758, 3761, 3762, 3707, 3704, 3703, 3700, 3699, 3696, 3645, 3644, 3651,
3650, 3655, 3656, 3659, 644, 643, 640, 639, 626, 627, 516, 517, 504, 503,
500, 499, 482, 485, 486, 465, 466, 469, 420, 421, 422, 423, 438, 437, 434,
2135, 2136, 2139, 2140, 2143, 2112, 2115, 2116, 2089, 2090, 2093, 2076,
2075, 2072, 2071, 2054, 2057, 2058, 1923, 1924, 1927, 1910, 1909, 1906,
1905, 2788, 2787, 2782, 2783, 2812, 2813, 2808, 2807, 2832, 2831, 2828,
2851, 2848, 2847, 2946, 2945, 2942, 2965, 2962, 2961, 2982, 2981, 2978,
3001, 2998, 2997, 3870, 3869, 3866, 3865, 3852, 3853, 3742, 3743, 3730,
3729, 3726, 3725, 3708, 3711, 3712, 3691, 3692, 3695, 3646, 3647, 3648,
3649, 3664, 3663, 3660, 645, 642, 641, 638, 629, 628, 515, 514, 505, 502,
501, 498, 483, 484, 487, 464, 467, 468, 453, 452, 451, 450, 439, 436, 435,
2134, 2137, 2138, 2141, 2142, 2113, 2114, 2117, 2088, 2091, 2092, 2077,
2074, 2073, 2070, 2055, 2056, 2059, 1922, 1925, 1926, 1911, 1908, 1907,
1904, 2789, 2786, 2785, 2784, 2811, 2810, 2809, 2806, 2833, 2830, 2829,
2850, 2849, 2846, 2947, 2944, 2943, 2964, 2963, 2960, 2983, 2980, 2979,
3000, 2999, 2996, 3871, 3868, 3867, 3864, 3855, 3854, 3741, 3740, 3731,
3728, 3727, 3724, 3709, 3710, 3713, 3690, 3693, 3694, 3679, 3678, 3677,
3676, 3665, 3662, 3661, 646, 647, 636, 637, 630, 631, 512, 513, 506, 507,
496, 497, 492, 491, 488, 463, 460, 459, 454, 455, 448, 449, 440, 441, 442,
2133, 2130, 2129, 2126, 2125, 2122, 2121, 2118, 2087, 2084, 2083, 2078,
2079, 2068, 2069, 2064, 2063, 2060, 1921, 1918, 1917, 1912, 1913, 1902,
1903, 2790, 2793, 2794, 2797, 2798, 2801, 2802, 2805, 2834, 2837, 2838,
2841, 2842, 2845, 2948, 2951, 2952, 2955, 2956, 2959, 2984, 2987, 2988,
2991, 2992, 2995, 3872, 3873, 3862, 3863, 3856, 3857, 3738, 3739, 3732,
3733, 3722, 3723, 3718, 3717, 3714, 3689, 3686, 3685, 3680, 3681, 3674,
3675, 3666, 3667, 3668, 649, 648, 635, 634, 633, 632, 511, 510, 509, 508,
495, 494, 493, 490, 489, 462, 461, 458, 457, 456, 447, 446, 445, 444, 443,
2132, 2131, 2128, 2127, 2124, 2123, 2120, 2119, 2086, 2085, 2082, 2081,
2080, 2067, 2066, 2065, 2062, 2061, 1920, 1919, 1916, 1915, 1914, 1901,
1900, 2791, 2792, 2795, 2796, 2799, 2800, 2803, 2804, 2835, 2836, 2839,
2840, 2843, 2844, 2949, 2950, 2953, 2954, 2957, 2958, 2985, 2986, 2989,
2990, 2993, 2994, 3875, 3874, 3861, 3860, 3859, 3858, 3737, 3736, 3735,
3734, 3721, 3720, 3719, 3716, 3715, 3688, 3687, 3684, 3683, 3682, 3673,
3672, 3671, 3670, 3669, 650, 653, 654, 681, 682, 685, 686, 687, 696, 697,
698, 701, 702, 1239, 1240, 1241, 1250, 1251, 1252, 1255, 1256, 1257, 1294,
1295, 1296, 1299, 1300, 1303, 1304, 1331, 1332, 1335, 1336, 1337, 1346,
1347, 1348, 1349, 1850, 1851, 1852, 1853, 1862, 1863, 1864, 1867, 1868,
1895, 1896, 1899, 4970, 4969, 4966, 4965, 4962, 4961, 4934, 4933, 4930,
4929, 4926, 4925, 4820, 4819, 4816, 4815, 4812, 4811, 4780, 4779, 4776,
4775, 4772, 4771, 4768, 4767, 3876, 3877, 3886, 3887, 3888, 3889, 4018,
4019, 4020, 4021, 4030, 4031, 4032, 4035, 4036, 4069, 4070, 4073, 4074,
4075, 4088, 4089, 4090, 4093, 4094, 651, 652, 655, 680, 683, 684, 689, 688,
695, 694, 699, 700, 703, 1238, 1243, 1242, 1249, 1248, 1253, 1254, 1259,
1258, 1293, 1292, 1297, 1298, 1301, 1302, 1305, 1330, 1333, 1334, 1339,
1338, 1345, 1344, 1351, 1350, 1849, 1848, 1855, 1854, 1861, 1860, 1865,
1866, 1869, 1894, 1897, 1898, 4971, 4968, 4967, 4964, 4963, 4960, 4935,
4932, 4931, 4928, 4927, 4924, 4821, 4818, 4817, 4814, 4813, 4810, 4781,
4778, 4777, 4774, 4773, 4770, 4769, 4766, 3879, 3878, 3885, 3884, 3891,
3890, 4017, 4016, 4023, 4022, 4029, 4028, 4033, 4034, 4037, 4068, 4071,
4072, 4077, 4076, 4087, 4086, 4091, 4092, 4095, 660, 659, 656, 679, 676,
675, 690, 691, 692, 693, 708, 707, 704, 1237, 1244, 1245, 1246, 1247, 1266,
1265, 1260, 1261, 1290, 1291, 1286, 1285, 1310, 1309, 1306, 1329, 1326,
1325, 1340, 1341, 1342, 1343, 1352, 1353, 1846, 1847, 1856, 1857, 1858,
1859, 1874, 1873, 1870, 1893, 1890, 1889, 4972, 4975, 4976, 4955, 4956,
4959, 4936, 4939, 4940, 4919, 4920, 4923, 4822, 4825, 4826, 4805, 4806,
4809, 4782, 4785, 4786, 4787, 4760, 4761, 4762, 4765, 3880, 3881, 3882,
3883, 3892, 3893, 4014, 4015, 4024, 4025, 4026, 4027, 4042, 4041, 4038,
4067, 4064, 4063, 4078, 4081, 4082, 4085, 4100, 4099, 4096, 661, 658, 657,
678, 677, 674, 723, 722, 721, 720, 709, 706, 705, 1236, 1229, 1228, 1227,
1226, 1267, 1264, 1263, 1262, 1289, 1288, 1287, 1284, 1311, 1308, 1307,
1328, 1327, 1324, 1367, 1366, 1365, 1364, 1355, 1354, 1845, 1844, 1835,
1834, 1833, 1832, 1875, 1872, 1871, 1892, 1891, 1888, 4973, 4974, 4977,
4954, 4957, 4958, 4937, 4938, 4941, 4918, 4921, 4922, 4823, 4824, 4827,
4804, 4807, 4808, 4783, 4784, 4789, 4788, 4759, 4758, 4763, 4764, 3907,
3906, 3905, 3904, 3895, 3894, 4013, 4012, 4003, 4002, 4001, 4000, 4043,
4040, 4039, 4066, 4065, 4062, 4079, 4080, 4083, 4084, 4101, 4098, 4097,
662, 665, 666, 669, 670, 673, 724, 725, 718, 719, 710, 711, 712, 1235,
1230, 1231, 1224, 1225, 1268, 1271, 1272, 1275, 1276, 1279, 1280, 1283,
1312, 1315, 1316, 1319, 1320, 1323, 1368, 1369, 1362, 1363, 1356, 1357,
1842, 1843, 1836, 1837, 1830, 1831, 1876, 1879, 1880, 1883, 1884, 1887,
4982, 4981, 4978, 4953, 4950, 4949, 4946, 4945, 4942, 4917, 4914, 4913,
4832, 4831, 4828, 4803, 4800, 4799, 4796, 4795, 4790, 4791, 4756, 4757,
4752, 4751, 3908, 3909, 3902, 3903, 3896, 3897, 4010, 4011, 4004, 4005,
3998, 3999, 4044, 4045, 4054, 4055, 4056, 4061, 4124, 4123, 4120, 4119,
4102, 4105, 4106, 663, 664, 667, 668, 671, 672, 727, 726, 717, 716, 715,
714, 713, 1234, 1233, 1232, 1223, 1222, 1269, 1270, 1273, 1274, 1277, 1278,
1281, 1282, 1313, 1314, 1317, 1318, 1321, 1322, 1371, 1370, 1361, 1360,
1359, 1358, 1841, 1840, 1839, 1838, 1829, 1828, 1877, 1878, 1881, 1882,
1885, 1886, 4983, 4980, 4979, 4952, 4951, 4948, 4947, 4944, 4943, 4916,
4915, 4912, 4833, 4830, 4829, 4802, 4801, 4798, 4797, 4794, 4793, 4792,
4755, 4754, 4753, 4750, 3911, 3910, 3901, 3900, 3899, 3898, 4009, 4008,
4007, 4006, 3997, 3996, 4047, 4046, 4053, 4052, 4057, 4060, 4125, 4122,
4121, 4118, 4103, 4104, 4107, 792, 791, 788, 787, 784, 783, 728, 729, 738,
739, 740, 743, 744, 1209, 1210, 1211, 1220, 1221, 1174, 1173, 1170, 1169,
1166, 1165, 1162, 1161, 1430, 1429, 1426, 1425, 1422, 1421, 1372, 1373,
1382, 1383, 1384, 1385, 1814, 1815, 1816, 1817, 1826, 1827, 1778, 1777,
1774, 1773, 1770, 1769, 4984, 4985, 4994, 4995, 4996, 4997, 4898, 4899,
4900, 4901, 4910, 4911, 4834, 4835, 4844, 4845, 4846, 4849, 4850, 4735,
4736, 4737, 4738, 4739, 4748, 4749, 3912, 3915, 3916, 3949, 3950, 3953,
3954, 3957, 3958, 3991, 3992, 3995, 4048, 4049, 4050, 4051, 4058, 4059,
4126, 4127, 4116, 4117, 4112, 4111, 4108, 793, 790, 789, 786, 785, 782,
731, 730, 737, 736, 741, 742, 745, 1208, 1213, 1212, 1219, 1218, 1175,
1172, 1171, 1168, 1167, 1164, 1163, 1160, 1431, 1428, 1427, 1424, 1423,
1420, 1375, 1374, 1381, 1380, 1387, 1386, 1813, 1812, 1819, 1818, 1825,
1824, 1779, 1776, 1775, 1772, 1771, 1768, 4987, 4986, 4993, 4992, 4999,
4998, 4897, 4896, 4903, 4902, 4909, 4908, 4837, 4836, 4843, 4842, 4847,
4848, 4851, 4734, 4733, 4732, 4741, 4740, 4747, 4746, 3913, 3914, 3917,
3948, 3951, 3952, 3955, 3956, 3959, 3990, 3993, 3994, 4199, 4198, 4191,
4190, 4189, 4188, 4129, 4128, 4115, 4114, 4113, 4110, 4109, 794, 797, 798,
777, 778, 781, 732, 733, 734, 735, 750, 749, 746, 1207, 1214, 1215, 1216,
1217, 1176, 1179, 1180, 1181, 1154, 1155, 1156, 1159, 1432, 1435, 1436,
1415, 1416, 1419, 1376, 1377, 1378, 1379, 1388, 1389, 1810, 1811, 1820,
1821, 1822, 1823, 1780, 1783, 1784, 1763, 1764, 1767, 4988, 4989, 4990,
4991, 5000, 5001, 4894, 4895, 4904, 4905, 4906, 4907, 4838, 4839, 4840,
4841, 4856, 4855, 4852, 4727, 4728, 4731, 4742, 4743, 4744, 4745, 3922,
3921, 3918, 3947, 3944, 3943, 3964, 3963, 3960, 3989, 3986, 3985, 4200,
4197, 4192, 4193, 4186, 4187, 4130, 4131, 4140, 4141, 4142, 4145, 4146,
795, 796, 799, 776, 779, 780, 765, 764, 763, 762, 751, 748, 747, 1206,
1199, 1198, 1197, 1196, 1177, 1178, 1183, 1182, 1153, 1152, 1157, 1158,
1433, 1434, 1437, 1414, 1417, 1418, 1403, 1402, 1401, 1400, 1391, 1390,
1809, 1808, 1799, 1798, 1797, 1796, 1781, 1782, 1785, 1762, 1765, 1766,
5015, 5014, 5013, 5012, 5003, 5002, 4893, 4892, 4883, 4882, 4881, 4880,
4871, 4870, 4869, 4868, 4857, 4854, 4853, 4726, 4729, 4730, 4715, 4714,
4713, 4712, 3923, 3920, 3919, 3946, 3945, 3942, 3965, 3962, 3961, 3988,
3987, 3984, 4201, 4196, 4195, 4194, 4185, 4184, 4133, 4132, 4139, 4138,
4143, 4144, 4147, 804, 803, 800, 775, 772, 771, 766, 767, 760, 761, 752,
753, 754, 1205, 1200, 1201, 1194, 1195, 1190, 1189, 1184, 1185, 1150, 1151,
1146, 1145, 1442, 1441, 1438, 1413, 1410, 1409, 1404, 1405, 1398, 1399,
1392, 1393, 1806, 1807, 1800, 1801, 1794, 1795, 1790, 1789, 1786, 1761,
1758, 1757, 5016, 5017, 5010, 5011, 5004, 5005, 4890, 4891, 4884, 4885,
4878, 4879, 4872, 4873, 4866, 4867, 4858, 4859, 4860, 4725, 4722, 4721,
4716, 4717, 4710, 4711, 3924, 3925, 3934, 3935, 3936, 3941, 3966, 3967,
3976, 3977, 3978, 3983, 4202, 4205, 4206, 4179, 4180, 4183, 4134, 4135,
4136, 4137, 4152, 4151, 4148, 805, 802, 801, 774, 773, 770, 769, 768, 759,
758, 757, 756, 755, 1204, 1203, 1202, 1193, 1192, 1191, 1188, 1187, 1186,
1149, 1148, 1147, 1144, 1443, 1440, 1439, 1412, 1411, 1408, 1407, 1406,
1397, 1396, 1395, 1394, 1805, 1804, 1803, 1802, 1793, 1792, 1791, 1788,
1787, 1760, 1759, 1756, 5019, 5018, 5009, 5008, 5007, 5006, 4889, 4888,
4887, 4886, 4877, 4876, 4875, 4874, 4865, 4864, 4863, 4862, 4861, 4724,
4723, 4720, 4719, 4718, 4709, 4708, 3927, 3926, 3933, 3932, 3937, 3940,
3969, 3968, 3975, 3974, 3979, 3982, 4203, 4204, 4207, 4178, 4181, 4182,
4167, 4166, 4165, 4164, 4153, 4150, 4149, 806, 807, 816, 817, 818, 821,
822, 973, 974, 975, 976, 977, 986, 987, 988, 989, 998, 999, 1000, 1001,
1130, 1131, 1132, 1133, 1142, 1143, 1444, 1445, 1454, 1455, 1456, 1457,
1586, 1587, 1588, 1589, 1598, 1599, 1600, 1601, 1610, 1611, 1612, 1613,
1742, 1743, 1744, 1745, 1754, 1755, 5020, 5023, 5024, 5057, 5058, 5061,
5062, 5063, 5076, 5077, 5078, 5081, 5082, 4639, 4640, 4641, 4650, 4651,
4652, 4655, 4656, 4657, 4702, 4703, 4704, 4707, 3928, 3929, 3930, 3931,
3938, 3939, 3970, 3971, 3972, 3973, 3980, 3981, 4212, 4211, 4208, 4177,
4174, 4173, 4168, 4169, 4162, 4163, 4154, 4155, 4156, 809, 808, 815, 814,
819, 820, 823, 972, 971, 970, 979, 978, 985, 984, 991, 990, 997, 996, 1003,
1002, 1129, 1128, 1135, 1134, 1141, 1140, 1447, 1446, 1453, 1452, 1459,
1458, 1585, 1584, 1591, 1590, 1597, 1596, 1603, 1602, 1609, 1608, 1615,
1614, 1741, 1740, 1747, 1746, 1753, 1752, 5021, 5022, 5025, 5056, 5059,
5060, 5065, 5064, 5075, 5074, 5079, 5080, 5083, 4638, 4643, 4642, 4649,
4648, 4653, 4654, 4659, 4658, 4701, 4700, 4705, 4706, 4465, 4464, 4463,
4462, 4461, 4460, 4435, 4434, 4433, 4432, 4431, 4430, 4213, 4210, 4209,
4176, 4175, 4172, 4171, 4170, 4161, 4160, 4159, 4158, 4157, 810, 811, 812,
813, 828, 827, 824, 965, 966, 969, 980, 981, 982, 983, 992, 993, 994, 995,
1004, 1005, 1126, 1127, 1136, 1137, 1138, 1139, 1448, 1449, 1450, 1451,
1460, 1461, 1582, 1583, 1592, 1593, 1594, 1595, 1604, 1605, 1606, 1607,
1616, 1617, 1738, 1739, 1748, 1749, 1750, 1751, 5030, 5029, 5026, 5055,
5052, 5051, 5066, 5069, 5070, 5073, 5088, 5087, 5084, 4637, 4644, 4645,
4646, 4647, 4666, 4665, 4660, 4661, 4698, 4699, 4694, 4693, 4466, 4469,
4470, 4455, 4456, 4459, 4436, 4439, 4440, 4425, 4426, 4429, 4214, 4217,
4218, 4245, 4246, 4249, 4250, 4251, 4260, 4261, 4262, 4265, 4266, 843, 842,
841, 840, 829, 826, 825, 964, 967, 968, 953, 952, 951, 950, 1019, 1018,
1017, 1016, 1007, 1006, 1125, 1124, 1115, 1114, 1113, 1112, 1475, 1474,
1473, 1472, 1463, 1462, 1581, 1580, 1571, 1570, 1569, 1568, 1631, 1630,
1629, 1628, 1619, 1618, 1737, 1736, 1727, 1726, 1725, 1724, 5031, 5028,
5027, 5054, 5053, 5050, 5067, 5068, 5071, 5072, 5089, 5086, 5085, 4636,
4629, 4628, 4627, 4626, 4667, 4664, 4663, 4662, 4697, 4696, 4695, 4692,
4467, 4468, 4471, 4454, 4457, 4458, 4437, 4438, 4441, 4424, 4427, 4428,
4215, 4216, 4219, 4244, 4247, 4248, 4253, 4252, 4259, 4258, 4263, 4264,
4267, 844, 845, 838, 839, 830, 831, 832, 963, 960, 959, 954, 955, 948, 949,
1020, 1021, 1014, 1015, 1008, 1009, 1122, 1123, 1116, 1117, 1110, 1111,
1476, 1477, 1470, 1471, 1464, 1465, 1578, 1579, 1572, 1573, 1566, 1567,
1632, 1633, 1626, 1627, 1620, 1621, 1734, 1735, 1728, 1729, 1722, 1723,
5032, 5033, 5042, 5043, 5044, 5049, 5112, 5111, 5108, 5107, 5090, 5093,
5094, 4635, 4630, 4631, 4624, 4625, 4668, 4669, 4678, 4679, 4680, 4681,
4690, 4691, 4476, 4475, 4472, 4453, 4450, 4449, 4446, 4445, 4442, 4423,
4420, 4419, 4224, 4223, 4220, 4243, 4240, 4239, 4254, 4255, 4256, 4257,
4272, 4271, 4268, 847, 846, 837, 836, 835, 834, 833, 962, 961, 958, 957,
956, 947, 946, 1023, 1022, 1013, 1012, 1011, 1010, 1121, 1120, 1119, 1118,
1109, 1108, 1479, 1478, 1469, 1468, 1467, 1466, 1577, 1576, 1575, 1574,
1565, 1564, 1635, 1634, 1625, 1624, 1623, 1622, 1733, 1732, 1731, 1730,
1721, 1720, 5035, 5034, 5041, 5040, 5045, 5048, 5113, 5110, 5109, 5106,
5091, 5092, 5095, 4634, 4633, 4632, 4623, 4622, 4671, 4670, 4677, 4676,
4683, 4682, 4689, 4688, 4477, 4474, 4473, 4452, 4451, 4448, 4447, 4444,
4443, 4422, 4421, 4418, 4225, 4222, 4221, 4242, 4241, 4238, 4287, 4286,
4285, 4284, 4273, 4270, 4269, 848, 851, 852, 853, 898, 899, 900, 903, 904,
907, 908, 941, 942, 945, 1024, 1027, 1028, 1061, 1062, 1065, 1066, 1069,
1070, 1103, 1104, 1107, 1480, 1483, 1484, 1517, 1518, 1521, 1522, 1525,
1526, 1559, 1560, 1563, 1636, 1639, 1640, 1673, 1674, 1677, 1678, 1681,
1682, 1715, 1716, 1719, 5036, 5037, 5038, 5039, 5046, 5047, 5114, 5115,
5104, 5105, 5100, 5099, 5096, 4613, 4614, 4617, 4618, 4621, 4672, 4673,
4674, 4675, 4684, 4685, 4686, 4687, 4478, 4479, 4492, 4493, 4494, 4495,
4400, 4401, 4402, 4403, 4416, 4417, 4226, 4229, 4230, 4233, 4234, 4237,
4288, 4289, 4282, 4283, 4274, 4275, 4276, 849, 850, 855, 854, 897, 896,
901, 902, 905, 906, 909, 940, 943, 944, 1025, 1026, 1029, 1060, 1063, 1064,
1067, 1068, 1071, 1102, 1105, 1106, 1481, 1482, 1485, 1516, 1519, 1520,
1523, 1524, 1527, 1558, 1561, 1562, 1637, 1638, 1641, 1672, 1675, 1676,
1679, 1680, 1683, 1714, 1717, 1718, 5187, 5186, 5179, 5178, 5177, 5176,
5117, 5116, 5103, 5102, 5101, 5098, 5097, 4612, 4615, 4616, 4619, 4620,
4561, 4560, 4559, 4558, 4549, 4548, 4547, 4546, 4481, 4480, 4491, 4490,
4497, 4496, 4399, 4398, 4405, 4404, 4415, 4414, 4227, 4228, 4231, 4232,
4235, 4236, 4291, 4290, 4281, 4280, 4279, 4278, 4277, 862, 861, 856, 857,
894, 895, 890, 889, 914, 913, 910, 939, 936, 935, 1034, 1033, 1030, 1059,
1056, 1055, 1076, 1075, 1072, 1101, 1098, 1097, 1490, 1489, 1486, 1515,
1512, 1511, 1532, 1531, 1528, 1557, 1554, 1553, 1646, 1645, 1642, 1671,
1668, 1667, 1688, 1687, 1684, 1713, 1710, 1709, 5188, 5185, 5180, 5181,
5174, 5175, 5118, 5119, 5128, 5129, 5130, 5133, 5134, 4611, 4608, 4607,
4604, 4603, 4562, 4563, 4556, 4557, 4550, 4551, 4544, 4545, 4482, 4485,
4486, 4489, 4498, 4499, 4396, 4397, 4406, 4409, 4410, 4413, 4356, 4355,
4352, 4351, 4348, 4347, 4292, 4293, 4302, 4303, 4304, 4307, 4308, 863, 860,
859, 858, 893, 892, 891, 888, 915, 912, 911, 938, 937, 934, 1035, 1032,
1031, 1058, 1057, 1054, 1077, 1074, 1073, 1100, 1099, 1096, 1491, 1488,
1487, 1514, 1513, 1510, 1533, 1530, 1529, 1556, 1555, 1552, 1647, 1644,
1643, 1670, 1669, 1666, 1689, 1686, 1685, 1712, 1711, 1708, 5189, 5184,
5183, 5182, 5173, 5172, 5121, 5120, 5127, 5126, 5131, 5132, 5135, 4610,
4609, 4606, 4605, 4602, 4565, 4564, 4555, 4554, 4553, 4552, 4543, 4542,
4483, 4484, 4487, 4488, 4501, 4500, 4395, 4394, 4407, 4408, 4411, 4412,
4357, 4354, 4353, 4350, 4349, 4346, 4295, 4294, 4301, 4300, 4305, 4306,
4309, 864, 865, 874, 875, 876, 877, 886, 887, 916, 917, 926, 927, 928, 933,
1036, 1037, 1046, 1047, 1048, 1053, 1078, 1079, 1088, 1089, 1090, 1095,
1492, 1493, 1502, 1503, 1504, 1509, 1534, 1535, 1544, 1545, 1546, 1551,
1648, 1649, 1658, 1659, 1660, 1665, 1690, 1691, 1700, 1701, 1702, 1707,
5190, 5193, 5194, 5167, 5168, 5171, 5122, 5123, 5124, 5125, 5140, 5139,
5136, 4593, 4594, 4597, 4598, 4601, 4566, 4569, 4570, 4571, 4536, 4537,
4538, 4541, 4520, 4519, 4516, 4515, 4502, 4503, 4392, 4393, 4380, 4379,
4376, 4375, 4358, 4361, 4362, 4341, 4342, 4345, 4296, 4297, 4298, 4299,
4314, 4313, 4310, 867, 866, 873, 872, 879, 878, 885, 884, 919, 918, 925,
924, 929, 932, 1039, 1038, 1045, 1044, 1049, 1052, 1081, 1080, 1087, 1086,
1091, 1094, 1495, 1494, 1501, 1500, 1505, 1508, 1537, 1536, 1543, 1542,
1547, 1550, 1651, 1650, 1657, 1656, 1661, 1664, 1693, 1692, 1699, 1698,
1703, 1706, 5191, 5192, 5195, 5166, 5169, 5170, 5155, 5154, 5153, 5152,
5141, 5138, 5137, 4592, 4595, 4596, 4599, 4600, 4567, 4568, 4573, 4572,
4535, 4534, 4539, 4540, 4521, 4518, 4517, 4514, 4505, 4504, 4391, 4390,
4381, 4378, 4377, 4374, 4359, 4360, 4363, 4340, 4343, 4344, 4329, 4328,
4327, 4326, 4315, 4312, 4311, 868, 869, 870, 871, 880, 881, 882, 883, 920,
921, 922, 923, 930, 931, 1040, 1041, 1042, 1043, 1050, 1051, 1082, 1083,
1084, 1085, 1092, 1093, 1496, 1497, 1498, 1499, 1506, 1507, 1538, 1539,
1540, 1541, 1548, 1549, 1652, 1653, 1654, 1655, 1662, 1663, 1694, 1695,
1696, 1697, 1704, 1705, 5200, 5199, 5196, 5165, 5162, 5161, 5156, 5157,
5150, 5151, 5142, 5143, 5144, 4591, 4588, 4587, 4584, 4583, 4580, 4579,
4574, 4575, 4532, 4533, 4528, 4527, 4522, 4523, 4512, 4513, 4506, 4507,
4388, 4389, 4382, 4383, 4372, 4373, 4368, 4367, 4364, 4339, 4336, 4335,
4330, 4331, 4324, 4325, 4316, 4317, 4318, 9535, 9534, 9531, 9530, 9527,
9526, 9499, 9498, 9495, 9494, 9491, 9490, 9391, 9390, 9387, 9386, 9383,
9382, 9355, 9354, 9351, 9350, 9347, 9346, 8897, 8896, 8893, 8892, 8889,
8888, 8861, 8860, 8857, 8856, 8853, 8852, 8747, 8746, 8743, 8742, 8739,
8738, 8707, 8706, 8703, 8702, 8699, 8698, 8695, 8694, 5201, 5198, 5197,
5164, 5163, 5160, 5159, 5158, 5149, 5148, 5147, 5146, 5145, 4590, 4589,
4586, 4585, 4582, 4581, 4578, 4577, 4576, 4531, 4530, 4529, 4526, 4525,
4524, 4511, 4510, 4509, 4508, 4387, 4386, 4385, 4384, 4371, 4370, 4369,
4366, 4365, 4338, 4337, 4334, 4333, 4332, 4323, 4322, 4321, 4320, 4319,
9536, 9533, 9532, 9529, 9528, 9525, 9500, 9497, 9496, 9493, 9492, 9489,
9392, 9389, 9388, 9385, 9384, 9381, 9356, 9353, 9352, 9349, 9348, 9345,
8898, 8895, 8894, 8891, 8890, 8887, 8862, 8859, 8858, 8855, 8854, 8851,
8748, 8745, 8744, 8741, 8740, 8737, 8708, 8705, 8704, 8701, 8700, 8697,
8696, 8693, 5202, 5205, 5206, 5233, 5234, 5237, 5238, 5239, 5248, 5249,
5250, 5253, 5254, 5791, 5792, 5793, 5802, 5803, 5804, 5807, 5808, 5809,
5846, 5847, 5848, 5851, 5852, 5853, 5862, 5863, 5864, 5865, 5994, 5995,
5996, 5997, 6006, 6007, 6008, 6011, 6012, 6045, 6046, 6049, 6050, 6051,
6064, 6065, 6066, 6069, 6070, 9537, 9540, 9541, 9520, 9521, 9524, 9501,
9504, 9505, 9484, 9485, 9488, 9393, 9396, 9397, 9376, 9377, 9380, 9357,
9360, 9361, 9340, 9341, 9344, 8899, 8902, 8903, 8882, 8883, 8886, 8863,
8866, 8867, 8846, 8847, 8850, 8749, 8752, 8753, 8732, 8733, 8736, 8709,
8712, 8713, 8714, 8687, 8688, 8689, 8692, 5203, 5204, 5207, 5232, 5235,
5236, 5241, 5240, 5247, 5246, 5251, 5252, 5255, 5790, 5795, 5794, 5801,
5800, 5805, 5806, 5811, 5810, 5845, 5844, 5849, 5850, 5855, 5854, 5861,
5860, 5867, 5866, 5993, 5992, 5999, 5998, 6005, 6004, 6009, 6010, 6013,
6044, 6047, 6048, 6053, 6052, 6063, 6062, 6067, 6068, 6071, 9538, 9539,
9542, 9519, 9522, 9523, 9502, 9503, 9506, 9483, 9486, 9487, 9394, 9395,
9398, 9375, 9378, 9379, 9358, 9359, 9362, 9339, 9342, 9343, 8900, 8901,
8904, 8881, 8884, 8885, 8864, 8865, 8868, 8845, 8848, 8849, 8750, 8751,
8754, 8731, 8734, 8735, 8710, 8711, 8716, 8715, 8686, 8685, 8690, 8691,
5212, 5211, 5208, 5231, 5228, 5227, 5242, 5243, 5244, 5245, 5260, 5259,
5256, 5789, 5796, 5797, 5798, 5799, 5818, 5817, 5812, 5813, 5842, 5843,
5838, 5837, 5856, 5857, 5858, 5859, 5868, 5869, 5990, 5991, 6000, 6001,
6002, 6003, 6018, 6017, 6014, 6043, 6040, 6039, 6054, 6057, 6058, 6061,
6076, 6075, 6072, 9547, 9546, 9543, 9518, 9515, 9514, 9511, 9510, 9507,
9482, 9479, 9478, 9403, 9402, 9399, 9374, 9371, 9370, 9367, 9366, 9363,
9338, 9335, 9334, 8909, 8908, 8905, 8880, 8877, 8876, 8873, 8872, 8869,
8844, 8841, 8840, 8759, 8758, 8755, 8730, 8727, 8726, 8723, 8722, 8717,
8718, 8683, 8684, 8679, 8678, 5213, 5210, 5209, 5230, 5229, 5226, 5275,
5274, 5273, 5272, 5261, 5258, 5257, 5788, 5781, 5780, 5779, 5778, 5819,
5816, 5815, 5814, 5841, 5840, 5839, 5836, 5883, 5882, 5881, 5880, 5871,
5870, 5989, 5988, 5979, 5978, 5977, 5976, 6019, 6016, 6015, 6042, 6041,
6038, 6055, 6056, 6059, 6060, 6077, 6074, 6073, 9548, 9545, 9544, 9517,
9516, 9513, 9512, 9509, 9508, 9481, 9480, 9477, 9404, 9401, 9400, 9373,
9372, 9369, 9368, 9365, 9364, 9337, 9336, 9333, 8910, 8907, 8906, 8879,
8878, 8875, 8874, 8871, 8870, 8843, 8842, 8839, 8760, 8757, 8756, 8729,
8728, 8725, 8724, 8721, 8720, 8719, 8682, 8681, 8680, 8677, 5214, 5217,
5218, 5221, 5222, 5225, 5276, 5277, 5270, 5271, 5262, 5263, 5264, 5787,
5782, 5783, 5776, 5777, 5820, 5823, 5824, 5827, 5828, 5831, 5832, 5835,
5884, 5885, 5878, 5879, 5872, 5873, 5986, 5987, 5980, 5981, 5974, 5975,
6020, 6021, 6030, 6031, 6032, 6037, 6100, 6099, 6096, 6095, 6078, 6081,
6082, 9549, 9550, 9559, 9560, 9561, 9562, 9463, 9464, 9465, 9466, 9475,
9476, 9405, 9406, 9415, 9416, 9417, 9418, 9319, 9320, 9321, 9322, 9331,
9332, 8911, 8912, 8921, 8922, 8923, 8924, 8825, 8826, 8827, 8828, 8837,
8838, 8761, 8762, 8771, 8772, 8773, 8776, 8777, 8662, 8663, 8664, 8665,
8666, 8675, 8676, 5215, 5216, 5219, 5220, 5223, 5224, 5279, 5278, 5269,
5268, 5267, 5266, 5265, 5786, 5785, 5784, 5775, 5774, 5821, 5822, 5825,
5826, 5829, 5830, 5833, 5834, 5887, 5886, 5877, 5876, 5875, 5874, 5985,
5984, 5983, 5982, 5973, 5972, 6023, 6022, 6029, 6028, 6033, 6036, 6101,
6098, 6097, 6094, 6079, 6080, 6083, 9552, 9551, 9558, 9557, 9564, 9563,
9462, 9461, 9468, 9467, 9474, 9473, 9408, 9407, 9414, 9413, 9420, 9419,
9318, 9317, 9324, 9323, 9330, 9329, 8914, 8913, 8920, 8919, 8926, 8925,
8824, 8823, 8830, 8829, 8836, 8835, 8764, 8763, 8770, 8769, 8774, 8775,
8778, 8661, 8660, 8659, 8668, 8667, 8674, 8673, 5344, 5343, 5340, 5339,
5336, 5335, 5280, 5281, 5290, 5291, 5292, 5295, 5296, 5761, 5762, 5763,
5772, 5773, 5726, 5725, 5722, 5721, 5718, 5717, 5714, 5713, 5888, 5891,
5892, 5925, 5926, 5929, 5930, 5933, 5934, 5967, 5968, 5971, 6024, 6025,
6026, 6027, 6034, 6035, 6102, 6103, 6092, 6093, 6088, 6087, 6084, 9553,
9554, 9555, 9556, 9565, 9566, 9459, 9460, 9469, 9470, 9471, 9472, 9409,
9410, 9411, 9412, 9421, 9422, 9315, 9316, 9325, 9326, 9327, 9328, 8915,
8916, 8917, 8918, 8927, 8928, 8821, 8822, 8831, 8832, 8833, 8834, 8765,
8766, 8767, 8768, 8783, 8782, 8779, 8654, 8655, 8658, 8669, 8670, 8671,
8672, 5345, 5342, 5341, 5338, 5337, 5334, 5283, 5282, 5289, 5288, 5293,
5294, 5297, 5760, 5765, 5764, 5771, 5770, 5727, 5724, 5723, 5720, 5719,
5716, 5715, 5712, 5889, 5890, 5893, 5924, 5927, 5928, 5931, 5932, 5935,
5966, 5969, 5970, 6175, 6174, 6167, 6166, 6165, 6164, 6105, 6104, 6091,
6090, 6089, 6086, 6085, 9580, 9579, 9578, 9577, 9568, 9567, 9458, 9457,
9448, 9447, 9446, 9445, 9436, 9435, 9434, 9433, 9424, 9423, 9314, 9313,
9304, 9303, 9302, 9301, 8942, 8941, 8940, 8939, 8930, 8929, 8820, 8819,
8810, 8809, 8808, 8807, 8798, 8797, 8796, 8795, 8784, 8781, 8780, 8653,
8656, 8657, 8642, 8641, 8640, 8639, 5346, 5349, 5350, 5329, 5330, 5333,
5284, 5285, 5286, 5287, 5302, 5301, 5298, 5759, 5766, 5767, 5768, 5769,
5728, 5731, 5732, 5733, 5706, 5707, 5708, 5711, 5898, 5897, 5894, 5923,
5920, 5919, 5940, 5939, 5936, 5965, 5962, 5961, 6176, 6173, 6168, 6169,
6162, 6163, 6106, 6107, 6116, 6117, 6118, 6121, 6122, 9581, 9582, 9575,
9576, 9569, 9570, 9455, 9456, 9449, 9450, 9443, 9444, 9437, 9438, 9431,
9432, 9425, 9426, 9311, 9312, 9305, 9306, 9299, 9300, 8943, 8944, 8937,
8938, 8931, 8932, 8817, 8818, 8811, 8812, 8805, 8806, 8799, 8800, 8793,
8794, 8785, 8786, 8787, 8652, 8649, 8648, 8643, 8644, 8637, 8638, 5347,
5348, 5351, 5328, 5331, 5332, 5317, 5316, 5315, 5314, 5303, 5300, 5299,
5758, 5751, 5750, 5749, 5748, 5729, 5730, 5735, 5734, 5705, 5704, 5709,
5710, 5899, 5896, 5895, 5922, 5921, 5918, 5941, 5938, 5937, 5964, 5963,
5960, 6177, 6172, 6171, 6170, 6161, 6160, 6109, 6108, 6115, 6114, 6119,
6120, 6123, 9584, 9583, 9574, 9573, 9572, 9571, 9454, 9453, 9452, 9451,
9442, 9441, 9440, 9439, 9430, 9429, 9428, 9427, 9310, 9309, 9308, 9307,
9298, 9297, 8946, 8945, 8936, 8935, 8934, 8933, 8816, 8815, 8814, 8813,
8804, 8803, 8802, 8801, 8792, 8791, 8790, 8789, 8788, 8651, 8650, 8647,
8646, 8645, 8636, 8635, 5356, 5355, 5352, 5327, 5324, 5323, 5318, 5319,
5312, 5313, 5304, 5305, 5306, 5757, 5752, 5753, 5746, 5747, 5742, 5741,
5736, 5737, 5702, 5703, 5698, 5697, 5900, 5901, 5910, 5911, 5912, 5917,
5942, 5943, 5952, 5953, 5954, 5959, 6178, 6181, 6182, 6155, 6156, 6159,
6110, 6111, 6112, 6113, 6128, 6127, 6124, 9585, 9588, 9589, 9622, 9623,
9626, 9627, 9628, 9641, 9642, 9643, 9644, 9241, 9242, 9243, 9244, 9253,
9254, 9255, 9258, 9259, 9292, 9293, 9296, 8947, 8950, 8951, 8984, 8985,
8988, 8989, 8990, 9003, 9004, 9005, 9008, 9009, 8566, 8567, 8568, 8577,
8578, 8579, 8582, 8583, 8584, 8629, 8630, 8631, 8634, 5357, 5354, 5353,
5326, 5325, 5322, 5321, 5320, 5311, 5310, 5309, 5308, 5307, 5756, 5755,
5754, 5745, 5744, 5743, 5740, 5739, 5738, 5701, 5700, 5699, 5696, 5903,
5902, 5909, 5908, 5913, 5916, 5945, 5944, 5951, 5950, 5955, 5958, 6179,
6180, 6183, 6154, 6157, 6158, 6143, 6142, 6141, 6140, 6129, 6126, 6125,
9586, 9587, 9590, 9621, 9624, 9625, 9630, 9629, 9640, 9639, 9646, 9645,
9240, 9239, 9246, 9245, 9252, 9251, 9256, 9257, 9260, 9291, 9294, 9295,
8948, 8949, 8952, 8983, 8986, 8987, 8992, 8991, 9002, 9001, 9006, 9007,
9010, 8565, 8570, 8569, 8576, 8575, 8580, 8581, 8586, 8585, 8628, 8627,
8632, 8633, 5358, 5359, 5368, 5369, 5370, 5373, 5374, 5525, 5526, 5527,
5528, 5529, 5538, 5539, 5540, 5541, 5550, 5551, 5552, 5553, 5682, 5683,
5684, 5685, 5694, 5695, 5904, 5905, 5906, 5907, 5914, 5915, 5946, 5947,
5948, 5949, 5956, 5957, 6188, 6187, 6184, 6153, 6150, 6149, 6144, 6145,
6138, 6139, 6130, 6131, 6132, 9595, 9594, 9591, 9620, 9617, 9616, 9631,
9634, 9635, 9638, 9647, 9648, 9237, 9238, 9247, 9248, 9249, 9250, 9265,
9264, 9261, 9290, 9287, 9286, 8957, 8956, 8953, 8982, 8979, 8978, 8993,
8996, 8997, 9000, 9015, 9014, 9011, 8564, 8571, 8572, 8573, 8574, 8593,
8592, 8587, 8588, 8625, 8626, 8621, 8620, 5361, 5360, 5367, 5366, 5371,
5372, 5375, 5524, 5523, 5522, 5531, 5530, 5537, 5536, 5543, 5542, 5549,
5548, 5555, 5554, 5681, 5680, 5687, 5686, 5693, 5692, 6441, 6440, 6439,
6438, 6437, 6436, 6411, 6410, 6409, 6408, 6407, 6406, 6189, 6186, 6185,
6152, 6151, 6148, 6147, 6146, 6137, 6136, 6135, 6134, 6133, 9596, 9593,
9592, 9619, 9618, 9615, 9632, 9633, 9636, 9637, 9650, 9649, 9236, 9235,
9226, 9225, 9224, 9223, 9266, 9263, 9262, 9289, 9288, 9285, 8958, 8955,
8954, 8981, 8980, 8977, 8994, 8995, 8998, 8999, 9016, 9013, 9012, 8563,
8556, 8555, 8554, 8553, 8594, 8591, 8590, 8589, 8624, 8623, 8622, 8619,
5362, 5363, 5364, 5365, 5380, 5379, 5376, 5517, 5518, 5521, 5532, 5533,
5534, 5535, 5544, 5545, 5546, 5547, 5556, 5557, 5678, 5679, 5688, 5689,
5690, 5691, 6442, 6445, 6446, 6431, 6432, 6435, 6412, 6415, 6416, 6401,
6402, 6405, 6190, 6193, 6194, 6221, 6222, 6225, 6226, 6227, 6236, 6237,
6238, 6241, 6242, 9597, 9598, 9607, 9608, 9609, 9614, 9669, 9668, 9665,
9664, 9651, 9652, 9233, 9234, 9227, 9228, 9221, 9222, 9267, 9268, 9277,
9278, 9279, 9284, 8959, 8960, 8969, 8970, 8971, 8976, 9039, 9038, 9035,
9034, 9017, 9020, 9021, 8562, 8557, 8558, 8551, 8552, 8595, 8596, 8605,
8606, 8607, 8608, 8617, 8618, 5395, 5394, 5393, 5392, 5381, 5378, 5377,
5516, 5519, 5520, 5505, 5504, 5503, 5502, 5571, 5570, 5569, 5568, 5559,
5558, 5677, 5676, 5667, 5666, 5665, 5664, 6443, 6444, 6447, 6430, 6433,
6434, 6413, 6414, 6417, 6400, 6403, 6404, 6191, 6192, 6195, 6220, 6223,
6224, 6229, 6228, 6235, 6234, 6239, 6240, 6243, 9600, 9599, 9606, 9605,
9610, 9613, 9670, 9667, 9666, 9663, 9654, 9653, 9232, 9231, 9230, 9229,
9220, 9219, 9270, 9269, 9276, 9275, 9280, 9283, 8962, 8961, 8968, 8967,
8972, 8975, 9040, 9037, 9036, 9033, 9018, 9019, 9022, 8561, 8560, 8559,
8550, 8549, 8598, 8597, 8604, 8603, 8610, 8609, 8616, 8615, 5396, 5397,
5390, 5391, 5382, 5383, 5384, 5515, 5512, 5511, 5506, 5507, 5500, 5501,
5572, 5573, 5566, 5567, 5560, 5561, 5674, 5675, 5668, 5669, 5662, 5663,
6452, 6451, 6448, 6429, 6426, 6425, 6422, 6421, 6418, 6399, 6396, 6395,
6200, 6199, 6196, 6219, 6216, 6215, 6230, 6231, 6232, 6233, 6248, 6247,
6244, 9601, 9602, 9603, 9604, 9611, 9612, 9671, 9672, 9661, 9662, 9655,
9656, 9201, 9202, 9203, 9204, 9217, 9218, 9271, 9272, 9273, 9274, 9281,
9282, 8963, 8964, 8965, 8966, 8973, 8974, 9041, 9042, 9031, 9032, 9027,
9026, 9023, 8540, 8541, 8544, 8545, 8548, 8599, 8600, 8601, 8602, 8611,
8612, 8613, 8614, 5399, 5398, 5389, 5388, 5387, 5386, 5385, 5514, 5513,
5510, 5509, 5508, 5499, 5498, 5575, 5574, 5565, 5564, 5563, 5562, 5673,
5672, 5671, 5670, 5661, 5660, 6453, 6450, 6449, 6428, 6427, 6424, 6423,
6420, 6419, 6398, 6397, 6394, 6201, 6198, 6197, 6218, 6217, 6214, 6263,
6262, 6261, 6260, 6249, 6246, 6245, 9738, 9737, 9730, 9729, 9728, 9727,
9674, 9673, 9660, 9659, 9658, 9657, 9200, 9199, 9206, 9205, 9216, 9215,
9156, 9155, 9148, 9147, 9146, 9145, 9114, 9113, 9106, 9105, 9104, 9103,
9044, 9043, 9030, 9029, 9028, 9025, 9024, 8539, 8542, 8543, 8546, 8547,
8488, 8487, 8486, 8485, 8476, 8475, 8474, 8473, 5400, 5403, 5404, 5405,
5450, 5451, 5452, 5455, 5456, 5459, 5460, 5493, 5494, 5497, 5576, 5579,
5580, 5613, 5614, 5617, 5618, 5621, 5622, 5655, 5656, 5659, 6454, 6455,
6468, 6469, 6470, 6471, 6376, 6377, 6378, 6379, 6392, 6393, 6202, 6205,
6206, 6209, 6210, 6213, 6264, 6265, 6258, 6259, 6250, 6251, 6252, 9739,
9736, 9731, 9732, 9725, 9726, 9675, 9676, 9685, 9686, 9687, 9688, 9197,
9198, 9207, 9210, 9211, 9214, 9157, 9154, 9149, 9150, 9143, 9144, 9115,
9112, 9107, 9108, 9101, 9102, 9045, 9046, 9055, 9056, 9057, 9060, 9061,
8538, 8535, 8534, 8531, 8530, 8489, 8490, 8483, 8484, 8477, 8478, 8471,
8472, 5401, 5402, 5407, 5406, 5449, 5448, 5453, 5454, 5457, 5458, 5461,
5492, 5495, 5496, 5577, 5578, 5581, 5612, 5615, 5616, 5619, 5620, 5623,
5654, 5657, 5658, 6457, 6456, 6467, 6466, 6473, 6472, 6375, 6374, 6381,
6380, 6391, 6390, 6203, 6204, 6207, 6208, 6211, 6212, 6267, 6266, 6257,
6256, 6255, 6254, 6253, 9740, 9735, 9734, 9733, 9724, 9723, 9678, 9677,
9684, 9683, 9690, 9689, 9196, 9195, 9208, 9209, 9212, 9213, 9158, 9153,
9152, 9151, 9142, 9141, 9116, 9111, 9110, 9109, 9100, 9099, 9048, 9047,
9054, 9053, 9058, 9059, 9062, 8537, 8536, 8533, 8532, 8529, 8492, 8491,
8482, 8481, 8480, 8479, 8470, 8469, 5414, 5413, 5408, 5409, 5446, 5447,
5442, 5441, 5466, 5465, 5462, 5491, 5488, 5487, 5586, 5585, 5582, 5611,
5608, 5607, 5628, 5627, 5624, 5653, 5650, 5649, 6458, 6461, 6462, 6465,
6474, 6475, 6372, 6373, 6382, 6385, 6386, 6389, 6332, 6331, 6328, 6327,
6324, 6323, 6268, 6269, 6278, 6279, 6280, 6283, 6284, 9741, 9744, 9745,
9718, 9719, 9722, 9679, 9680, 9681, 9682, 9691, 9692, 9193, 9194, 9181,
9180, 9177, 9176, 9159, 9162, 9163, 9136, 9137, 9140, 9117, 9120, 9121,
9094, 9095, 9098, 9049, 9050, 9051, 9052, 9067, 9066, 9063, 8520, 8521,
8524, 8525, 8528, 8493, 8496, 8497, 8498, 8463, 8464, 8465, 8468, 5415,
5412, 5411, 5410, 5445, 5444, 5443, 5440, 5467, 5464, 5463, 5490, 5489,
5486, 5587, 5584, 5583, 5610, 5609, 5606, 5629, 5626, 5625, 5652, 5651,
5648, 6459, 6460, 6463, 6464, 6477, 6476, 6371, 6370, 6383, 6384, 6387,
6388, 6333, 6330, 6329, 6326, 6325, 6322, 6271, 6270, 6277, 6276, 6281,
6282, 6285, 9742, 9743, 9746, 9717, 9720, 9721, 9706, 9705, 9704, 9703,
9694, 9693, 9192, 9191, 9182, 9179, 9178, 9175, 9160, 9161, 9164, 9135,
9138, 9139, 9118, 9119, 9122, 9093, 9096, 9097, 9082, 9081, 9080, 9079,
9068, 9065, 9064, 8519, 8522, 8523, 8526, 8527, 8494, 8495, 8500, 8499,
8462, 8461, 8466, 8467, 5416, 5417, 5426, 5427, 5428, 5429, 5438, 5439,
5468, 5469, 5478, 5479, 5480, 5485, 5588, 5589, 5598, 5599, 5600, 5605,
5630, 5631, 5640, 5641, 5642, 5647, 6496, 6495, 6492, 6491, 6478, 6479,
6368, 6369, 6356, 6355, 6352, 6351, 6334, 6337, 6338, 6317, 6318, 6321,
6272, 6273, 6274, 6275, 6290, 6289, 6286, 9751, 9750, 9747, 9716, 9713,
9712, 9707, 9708, 9701, 9702, 9695, 9696, 9189, 9190, 9183, 9184, 9173,
9174, 9169, 9168, 9165, 9134, 9131, 9130, 9127, 9126, 9123, 9092, 9089,
9088, 9083, 9084, 9077, 9078, 9069, 9070, 9071, 8518, 8515, 8514, 8511,
8510, 8507, 8506, 8501, 8502, 8459, 8460, 8455, 8454, 5419, 5418, 5425,
5424, 5431, 5430, 5437, 5436, 5471, 5470, 5477, 5476, 5481, 5484, 5591,
5590, 5597, 5596, 5601, 5604, 5633, 5632, 5639, 5638, 5643, 5646, 6497,
6494, 6493, 6490, 6481, 6480, 6367, 6366, 6357, 6354, 6353, 6350, 6335,
6336, 6339, 6316, 6319, 6320, 6305, 6304, 6303, 6302, 6291, 6288, 6287,
9752, 9749, 9748, 9715, 9714, 9711, 9710, 9709, 9700, 9699, 9698, 9697,
9188, 9187, 9186, 9185, 9172, 9171, 9170, 9167, 9166, 9133, 9132, 9129,
9128, 9125, 9124, 9091, 9090, 9087, 9086, 9085, 9076, 9075, 9074, 9073,
9072, 8517, 8516, 8513, 8512, 8509, 8508, 8505, 8504, 8503, 8458, 8457,
8456, 8453, 5420, 5421, 5422, 5423, 5432, 5433, 5434, 5435, 5472, 5473,
5474, 5475, 5482, 5483, 5592, 5593, 5594, 5595, 5602, 5603, 5634, 5635,
5636, 5637, 5644, 5645, 6498, 6499, 6488, 6489, 6482, 6483, 6364, 6365,
6358, 6359, 6348, 6349, 6344, 6343, 6340, 6315, 6312, 6311, 6306, 6307,
6300, 6301, 6292, 6293, 6294, 9753, 9754, 9763, 9764, 9765, 9766, 9895,
9896, 9897, 9898, 9907, 9908, 9909, 9912, 9913, 9946, 9947, 9950, 9951,
9952, 9965, 9966, 9967, 9970, 9971, 8222, 8223, 8224, 8233, 8234, 8235,
8238, 8239, 8266, 8267, 8270, 8271, 8272, 8281, 8282, 8283, 8286, 8287,
8438, 8439, 8440, 8441, 8442, 8451, 8452, 7571, 7570, 7567, 7566, 7563,
7562, 7535, 7534, 7531, 7530, 7527, 7526, 7421, 7420, 7417, 7416, 7413,
7412, 7381, 7380, 7377, 7376, 7373, 7372, 7369, 7368, 6501, 6500, 6487,
6486, 6485, 6484, 6363, 6362, 6361, 6360, 6347, 6346, 6345, 6342, 6341,
6314, 6313, 6310, 6309, 6308, 6299, 6298, 6297, 6296, 6295, 9756, 9755,
9762, 9761, 9768, 9767, 9894, 9893, 9900, 9899, 9906, 9905, 9910, 9911,
9914, 9945, 9948, 9949, 9954, 9953, 9964, 9963, 9968, 9969, 9972, 8221,
8226, 8225, 8232, 8231, 8236, 8237, 8240, 8265, 8268, 8269, 8274, 8273,
8280, 8279, 8284, 8285, 8288, 8437, 8436, 8435, 8444, 8443, 8450, 8449,
7572, 7569, 7568, 7565, 7564, 7561, 7536, 7533, 7532, 7529, 7528, 7525,
7422, 7419, 7418, 7415, 7414, 7411, 7382, 7379, 7378, 7375, 7374, 7371,
7370, 7367, 6502, 6503, 6512, 6513, 6514, 6515, 6632, 6633, 6634, 6635,
6644, 6645, 6646, 6649, 6650, 6677, 6678, 6681, 6682, 6683, 6692, 6693,
6694, 6697, 6698, 9757, 9758, 9759, 9760, 9769, 9770, 9891, 9892, 9901,
9902, 9903, 9904, 9919, 9918, 9915, 9944, 9941, 9940, 9955, 9958, 9959,
9962, 9977, 9976, 9973, 8220, 8227, 8228, 8229, 8230, 8245, 8244, 8241,
8264, 8261, 8260, 8275, 8276, 8277, 8278, 8293, 8292, 8289, 8430, 8431,
8434, 8445, 8446, 8447, 8448, 7573, 7576, 7577, 7556, 7557, 7560, 7537,
7540, 7541, 7520, 7521, 7524, 7423, 7426, 7427, 7406, 7407, 7410, 7383,
7386, 7387, 7388, 7361, 7362, 7363, 7366, 6505, 6504, 6511, 6510, 6517,
6516, 6631, 6630, 6637, 6636, 6643, 6642, 6647, 6648, 6651, 6676, 6679,
6680, 6685, 6684, 6691, 6690, 6695, 6696, 6699, 9784, 9783, 9782, 9781,
9772, 9771, 9890, 9889, 9880, 9879, 9878, 9877, 9920, 9917, 9916, 9943,
9942, 9939, 9956, 9957, 9960, 9961, 9978, 9975, 9974, 8219, 8212, 8211,
8210, 8209, 8246, 8243, 8242, 8263, 8262, 8259, 8308, 8307, 8306, 8305,
8294, 8291, 8290, 8429, 8432, 8433, 8418, 8417, 8416, 8415, 7574, 7575,
7578, 7555, 7558, 7559, 7538, 7539, 7542, 7519, 7522, 7523, 7424, 7425,
7428, 7405, 7408, 7409, 7384, 7385, 7390, 7389, 7360, 7359, 7364, 7365,
6506, 6507, 6508, 6509, 6518, 6519, 6628, 6629, 6638, 6639, 6640, 6641,
6656, 6655, 6652, 6675, 6672, 6671, 6686, 6687, 6688, 6689, 6704, 6703,
6700, 9785, 9786, 9779, 9780, 9773, 9774, 9887, 9888, 9881, 9882, 9875,
9876, 9921, 9922, 9931, 9932, 9933, 9938, 10001, 10000, 9997, 9996, 9979,
9982, 9983, 8218, 8213, 8214, 8207, 8208, 8247, 8250, 8251, 8254, 8255,
8258, 8309, 8310, 8303, 8304, 8295, 8296, 8297, 8428, 8425, 8424, 8419,
8420, 8413, 8414, 7583, 7582, 7579, 7554, 7551, 7550, 7547, 7546, 7543,
7518, 7515, 7514, 7433, 7432, 7429, 7404, 7401, 7400, 7397, 7396, 7391,
7392, 7357, 7358, 7353, 7352, 6533, 6532, 6531, 6530, 6521, 6520, 6627,
6626, 6617, 6616, 6615, 6614, 6657, 6654, 6653, 6674, 6673, 6670, 6719,
6718, 6717, 6716, 6705, 6702, 6701, 9788, 9787, 9778, 9777, 9776, 9775,
9886, 9885, 9884, 9883, 9874, 9873, 9924, 9923, 9930, 9929, 9934, 9937,
10002, 9999, 9998, 9995, 9980, 9981, 9984, 8217, 8216, 8215, 8206, 8205,
8248, 8249, 8252, 8253, 8256, 8257, 8312, 8311, 8302, 8301, 8300, 8299,
8298, 8427, 8426, 8423, 8422, 8421, 8412, 8411, 7584, 7581, 7580, 7553,
7552, 7549, 7548, 7545, 7544, 7517, 7516, 7513, 7434, 7431, 7430, 7403,
7402, 7399, 7398, 7395, 7394, 7393, 7356, 7355, 7354, 7351, 6534, 6535,
6528, 6529, 6522, 6523, 6624, 6625, 6618, 6619, 6612, 6613, 6658, 6661,
6662, 6665, 6666, 6669, 6720, 6721, 6714, 6715, 6706, 6707, 6708, 9789,
9792, 9793, 9826, 9827, 9830, 9831, 9834, 9835, 9868, 9869, 9872, 9925,
9926, 9927, 9928, 9935, 9936, 10003, 10004, 9993, 9994, 9989, 9988, 9985,
8192, 8193, 8194, 8203, 8204, 8161, 8160, 8157, 8156, 8153, 8152, 8313,
8316, 8317, 8318, 8363, 8364, 8365, 8368, 8369, 8372, 8373, 8406, 8407,
8410, 7585, 7586, 7595, 7596, 7597, 7598, 7499, 7500, 7501, 7502, 7511,
7512, 7435, 7436, 7445, 7446, 7447, 7450, 7451, 7336, 7337, 7338, 7339,
7340, 7349, 7350, 6537, 6536, 6527, 6526, 6525, 6524, 6623, 6622, 6621,
6620, 6611, 6610, 6659, 6660, 6663, 6664, 6667, 6668, 6723, 6722, 6713,
6712, 6711, 6710, 6709, 9790, 9791, 9794, 9825, 9828, 9829, 9832, 9833,
9836, 9867, 9870, 9871, 10076, 10075, 10068, 10067, 10066, 10065, 10006,
10005, 9992, 9991, 9990, 9987, 9986, 8191, 8196, 8195, 8202, 8201, 8162,
8159, 8158, 8155, 8154, 8151, 8314, 8315, 8320, 8319, 8362, 8361, 8366,
8367, 8370, 8371, 8374, 8405, 8408, 8409, 7588, 7587, 7594, 7593, 7600,
7599, 7498, 7497, 7504, 7503, 7510, 7509, 7438, 7437, 7444, 7443, 7448,
7449, 7452, 7335, 7334, 7333, 7342, 7341, 7348, 7347, 6538, 6541, 6542,
6569, 6570, 6573, 6574, 6577, 6578, 6605, 6606, 6609, 6788, 6787, 6784,
6783, 6780, 6779, 6724, 6725, 6734, 6735, 6736, 6739, 6740, 9799, 9798,
9795, 9824, 9821, 9820, 9841, 9840, 9837, 9866, 9863, 9862, 10077, 10074,
10069, 10070, 10063, 10064, 10007, 10008, 10017, 10018, 10019, 10022,
10023, 8190, 8197, 8198, 8199, 8200, 8163, 8166, 8167, 8146, 8147, 8150,
8327, 8326, 8321, 8322, 8359, 8360, 8355, 8354, 8379, 8378, 8375, 8404,
8401, 8400, 7589, 7590, 7591, 7592, 7601, 7602, 7495, 7496, 7505, 7506,
7507, 7508, 7439, 7440, 7441, 7442, 7457, 7456, 7453, 7328, 7329, 7332,
7343, 7344, 7345, 7346, 6539, 6540, 6543, 6568, 6571, 6572, 6575, 6576,
6579, 6604, 6607, 6608, 6789, 6786, 6785, 6782, 6781, 6778, 6727, 6726,
6733, 6732, 6737, 6738, 6741, 9800, 9797, 9796, 9823, 9822, 9819, 9842,
9839, 9838, 9865, 9864, 9861, 10078, 10073, 10072, 10071, 10062, 10061,
10010, 10009, 10016, 10015, 10020, 10021, 10024, 8189, 8182, 8181, 8180,
8179, 8164, 8165, 8168, 8145, 8148, 8149, 8328, 8325, 8324, 8323, 8358,
8357, 8356, 8353, 8380, 8377, 8376, 8403, 8402, 8399, 7616, 7615, 7614,
7613, 7604, 7603, 7494, 7493, 7484, 7483, 7482, 7481, 7472, 7471, 7470,
7469, 7458, 7455, 7454, 7327, 7330, 7331, 7316, 7315, 7314, 7313, 6548,
6547, 6544, 6567, 6564, 6563, 6584, 6583, 6580, 6603, 6600, 6599, 6790,
6793, 6794, 6773, 6774, 6777, 6728, 6729, 6730, 6731, 6746, 6745, 6742,
9801, 9802, 9811, 9812, 9813, 9818, 9843, 9844, 9853, 9854, 9855, 9860,
10079, 10082, 10083, 10056, 10057, 10060, 10011, 10012, 10013, 10014,
10029, 10028, 10025, 8188, 8183, 8184, 8177, 8178, 8173, 8172, 8169, 8144,
8141, 8140, 8329, 8330, 8339, 8340, 8341, 8342, 8351, 8352, 8381, 8382,
8391, 8392, 8393, 8398, 7617, 7618, 7611, 7612, 7605, 7606, 7491, 7492,
7485, 7486, 7479, 7480, 7473, 7474, 7467, 7468, 7459, 7460, 7461, 7326,
7323, 7322, 7317, 7318, 7311, 7312, 6549, 6546, 6545, 6566, 6565, 6562,
6585, 6582, 6581, 6602, 6601, 6598, 6791, 6792, 6795, 6772, 6775, 6776,
6761, 6760, 6759, 6758, 6747, 6744, 6743, 9804, 9803, 9810, 9809, 9814,
9817, 9846, 9845, 9852, 9851, 9856, 9859, 10080, 10081, 10084, 10055,
10058, 10059, 10044, 10043, 10042, 10041, 10030, 10027, 10026, 8187, 8186,
8185, 8176, 8175, 8174, 8171, 8170, 8143, 8142, 8139, 8332, 8331, 8338,
8337, 8344, 8343, 8350, 8349, 8384, 8383, 8390, 8389, 8394, 8397, 7620,
7619, 7610, 7609, 7608, 7607, 7490, 7489, 7488, 7487, 7478, 7477, 7476,
7475, 7466, 7465, 7464, 7463, 7462, 7325, 7324, 7321, 7320, 7319, 7310,
7309, 6550, 6553, 6554, 6557, 6558, 6561, 6586, 6589, 6590, 6593, 6594,
6597, 6800, 6799, 6796, 6771, 6768, 6767, 6762, 6763, 6756, 6757, 6748,
6749, 6750, 9805, 9806, 9807, 9808, 9815, 9816, 9847, 9848, 9849, 9850,
9857, 9858, 10089, 10088, 10085, 10054, 10051, 10050, 10045, 10046, 10039,
10040, 10031, 10032, 10033, 8084, 8085, 8086, 8095, 8096, 8097, 8100, 8101,
8134, 8135, 8138, 8333, 8334, 8335, 8336, 8345, 8346, 8347, 8348, 8385,
8386, 8387, 8388, 8395, 8396, 7621, 7624, 7625, 7658, 7659, 7662, 7663,
7664, 7677, 7678, 7679, 7682, 7683, 7240, 7241, 7242, 7251, 7252, 7253,
7256, 7257, 7258, 7303, 7304, 7305, 7308, 6551, 6552, 6555, 6556, 6559,
6560, 6587, 6588, 6591, 6592, 6595, 6596, 6801, 6798, 6797, 6770, 6769,
6766, 6765, 6764, 6755, 6754, 6753, 6752, 6751, 10342, 10341, 10340, 10339,
10338, 10337, 10312, 10311, 10310, 10309, 10308, 10307, 10090, 10087,
10086, 10053, 10052, 10049, 10048, 10047, 10038, 10037, 10036, 10035,
10034, 8083, 8088, 8087, 8094, 8093, 8098, 8099, 8102, 8133, 8136, 8137,
7916, 7915, 7914, 7913, 7912, 7911, 7890, 7889, 7888, 7887, 7870, 7869,
7868, 7867, 7622, 7623, 7626, 7657, 7660, 7661, 7666, 7665, 7676, 7675,
7680, 7681, 7684, 7239, 7244, 7243, 7250, 7249, 7254, 7255, 7260, 7259,
7302, 7301, 7306, 7307, 7066, 7065, 7064, 7063, 7062, 7061, 7036, 7035,
7034, 7033, 7032, 7031, 6802, 6805, 6806, 6833, 6834, 6837, 6838, 6839,
6848, 6849, 6850, 6853, 6854, 10343, 10346, 10347, 10332, 10333, 10336,
10313, 10316, 10317, 10302, 10303, 10306, 10091, 10094, 10095, 10122,
10123, 10126, 10127, 10128, 10137, 10138, 10139, 10142, 10143, 8082, 8089,
8090, 8091, 8092, 8107, 8106, 8103, 8132, 8129, 8128, 7917, 7920, 7921,
7906, 7907, 7910, 7891, 7892, 7885, 7886, 7871, 7872, 7865, 7866, 7631,
7630, 7627, 7656, 7653, 7652, 7667, 7670, 7671, 7674, 7689, 7688, 7685,
7238, 7245, 7246, 7247, 7248, 7267, 7266, 7261, 7262, 7299, 7300, 7295,
7294, 7067, 7070, 7071, 7056, 7057, 7060, 7037, 7040, 7041, 7026, 7027,
7030, 6803, 6804, 6807, 6832, 6835, 6836, 6841, 6840, 6847, 6846, 6851,
6852, 6855, 10344, 10345, 10348, 10331, 10334, 10335, 10314, 10315, 10318,
10301, 10304, 10305, 10092, 10093, 10096, 10121, 10124, 10125, 10130,
10129, 10136, 10135, 10140, 10141, 10144, 8081, 8074, 8073, 8072, 8071,
8108, 8105, 8104, 8131, 8130, 8127, 7918, 7919, 7922, 7905, 7908, 7909,
7894, 7893, 7884, 7883, 7874, 7873, 7864, 7863, 7632, 7629, 7628, 7655,
7654, 7651, 7668, 7669, 7672, 7673, 7690, 7687, 7686, 7237, 7230, 7229,
7228, 7227, 7268, 7265, 7264, 7263, 7298, 7297, 7296, 7293, 7068, 7069,
7072, 7055, 7058, 7059, 7038, 7039, 7042, 7025, 7028, 7029, 6812, 6811,
6808, 6831, 6828, 6827, 6842, 6843, 6844, 6845, 6860, 6859, 6856, 10353,
10352, 10349, 10330, 10327, 10326, 10323, 10322, 10319, 10300, 10297,
10296, 10101, 10100, 10097, 10120, 10117, 10116, 10131, 10132, 10133,
10134, 10149, 10148, 10145, 8080, 8075, 8076, 8069, 8070, 8109, 8110, 8119,
8120, 8121, 8126, 7927, 7926, 7923, 7904, 7901, 7900, 7895, 7896, 7881,
7882, 7875, 7876, 7861, 7862, 7633, 7634, 7643, 7644, 7645, 7650, 7713,
7712, 7709, 7708, 7691, 7694, 7695, 7236, 7231, 7232, 7225, 7226, 7269,
7270, 7279, 7280, 7281, 7282, 7291, 7292, 7077, 7076, 7073, 7054, 7051,
7050, 7047, 7046, 7043, 7024, 7021, 7020, 6813, 6810, 6809, 6830, 6829,
6826, 6875, 6874, 6873, 6872, 6861, 6858, 6857, 10354, 10351, 10350, 10329,
10328, 10325, 10324, 10321, 10320, 10299, 10298, 10295, 10102, 10099,
10098, 10119, 10118, 10115, 10164, 10163, 10162, 10161, 10150, 10147,
10146, 8079, 8078, 8077, 8068, 8067, 8112, 8111, 8118, 8117, 8122, 8125,
7928, 7925, 7924, 7903, 7902, 7899, 7898, 7897, 7880, 7879, 7878, 7877,
7860, 7859, 7636, 7635, 7642, 7641, 7646, 7649, 7714, 7711, 7710, 7707,
7692, 7693, 7696, 7235, 7234, 7233, 7224, 7223, 7272, 7271, 7278, 7277,
7284, 7283, 7290, 7289, 7078, 7075, 7074, 7053, 7052, 7049, 7048, 7045,
7044, 7023, 7022, 7019, 6814, 6817, 6818, 6821, 6822, 6825, 6876, 6877,
6870, 6871, 6862, 6863, 6864, 10355, 10356, 10369, 10370, 10371, 10372,
10277, 10278, 10279, 10280, 10293, 10294, 10103, 10106, 10107, 10110,
10111, 10114, 10165, 10166, 10159, 10160, 10151, 10152, 10153, 8058, 8059,
8062, 8063, 8066, 8113, 8114, 8115, 8116, 8123, 8124, 7929, 7930, 7943,
7944, 7945, 7948, 7949, 7838, 7839, 7842, 7843, 7844, 7857, 7858, 7637,
7638, 7639, 7640, 7647, 7648, 7715, 7716, 7705, 7706, 7701, 7700, 7697,
7214, 7215, 7218, 7219, 7222, 7273, 7274, 7275, 7276, 7285, 7286, 7287,
7288, 7079, 7080, 7093, 7094, 7095, 7096, 7001, 7002, 7003, 7004, 7017,
7018, 6815, 6816, 6819, 6820, 6823, 6824, 6879, 6878, 6869, 6868, 6867,
6866, 6865, 10358, 10357, 10368, 10367, 10374, 10373, 10276, 10275, 10282,
10281, 10292, 10291, 10104, 10105, 10108, 10109, 10112, 10113, 10168,
10167, 10158, 10157, 10156, 10155, 10154, 8057, 8060, 8061, 8064, 8065,
8012, 8011, 8004, 8003, 8002, 8001, 7932, 7931, 7942, 7941, 7946, 7947,
7950, 7837, 7840, 7841, 7846, 7845, 7856, 7855, 7788, 7787, 7780, 7779,
7778, 7777, 7718, 7717, 7704, 7703, 7702, 7699, 7698, 7213, 7216, 7217,
7220, 7221, 7162, 7161, 7160, 7159, 7150, 7149, 7148, 7147, 7082, 7081,
7092, 7091, 7098, 7097, 7000, 6999, 7006, 7005, 7016, 7015, 6956, 6955,
6948, 6947, 6946, 6945, 6880, 6881, 6890, 6891, 6892, 6895, 6896, 10359,
10362, 10363, 10366, 10375, 10376, 10273, 10274, 10283, 10286, 10287,
10290, 10233, 10232, 10229, 10228, 10225, 10224, 10169, 10170, 10179,
10180, 10181, 10184, 10185, 8056, 8053, 8052, 8049, 8048, 8013, 8010, 8005,
8006, 7999, 8000, 7933, 7936, 7937, 7940, 7955, 7954, 7951, 7836, 7833,
7832, 7847, 7850, 7851, 7854, 7789, 7786, 7781, 7782, 7775, 7776, 7719,
7720, 7729, 7730, 7731, 7734, 7735, 7212, 7209, 7208, 7205, 7204, 7163,
7164, 7157, 7158, 7151, 7152, 7145, 7146, 7083, 7086, 7087, 7090, 7099,
7100, 6997, 6998, 7007, 7010, 7011, 7014, 6957, 6954, 6949, 6950, 6943,
6944, 6883, 6882, 6889, 6888, 6893, 6894, 6897, 10360, 10361, 10364, 10365,
10378, 10377, 10272, 10271, 10284, 10285, 10288, 10289, 10234, 10231,
10230, 10227, 10226, 10223, 10172, 10171, 10178, 10177, 10182, 10183,
10186, 8055, 8054, 8051, 8050, 8047, 8014, 8009, 8008, 8007, 7998, 7997,
7934, 7935, 7938, 7939, 7956, 7953, 7952, 7835, 7834, 7831, 7848, 7849,
7852, 7853, 7790, 7785, 7784, 7783, 7774, 7773, 7722, 7721, 7728, 7727,
7732, 7733, 7736, 7211, 7210, 7207, 7206, 7203, 7166, 7165, 7156, 7155,
7154, 7153, 7144, 7143, 7084, 7085, 7088, 7089, 7102, 7101, 6996, 6995,
7008, 7009, 7012, 7013, 6958, 6953, 6952, 6951, 6942, 6941, 6884, 6885,
6886, 6887, 6902, 6901, 6898, 10397, 10396, 10393, 10392, 10379, 10380,
10269, 10270, 10257, 10256, 10253, 10252, 10235, 10238, 10239, 10218,
10219, 10222, 10173, 10174, 10175, 10176, 10191, 10190, 10187, 8038, 8039,
8042, 8043, 8046, 8015, 8018, 8019, 7992, 7993, 7996, 7979, 7978, 7975,
7974, 7957, 7960, 7961, 7826, 7827, 7830, 7813, 7812, 7809, 7808, 7791,
7794, 7795, 7768, 7769, 7772, 7723, 7724, 7725, 7726, 7741, 7740, 7737,
7194, 7195, 7198, 7199, 7202, 7167, 7170, 7171, 7172, 7137, 7138, 7139,
7142, 7121, 7120, 7117, 7116, 7103, 7104, 6993, 6994, 6981, 6980, 6977,
6976, 6959, 6962, 6963, 6936, 6937, 6940, 6923, 6922, 6919, 6918, 6903,
6900, 6899, 10398, 10395, 10394, 10391, 10382, 10381, 10268, 10267, 10258,
10255, 10254, 10251, 10236, 10237, 10240, 10217, 10220, 10221, 10206,
10205, 10204, 10203, 10192, 10189, 10188, 8037, 8040, 8041, 8044, 8045,
8016, 8017, 8020, 7991, 7994, 7995, 7980, 7977, 7976, 7973, 7958, 7959,
7962, 7825, 7828, 7829, 7814, 7811, 7810, 7807, 7792, 7793, 7796, 7767,
7770, 7771, 7756, 7755, 7754, 7753, 7742, 7739, 7738, 7193, 7196, 7197,
7200, 7201, 7168, 7169, 7174, 7173, 7136, 7135, 7140, 7141, 7122, 7119,
7118, 7115, 7106, 7105, 6992, 6991, 6982, 6979, 6978, 6975, 6960, 6961,
6964, 6935, 6938, 6939, 6924, 6921, 6920, 6917, 6904, 6905, 6906, 10399,
10400, 10389, 10390, 10383, 10384, 10265, 10266, 10259, 10260, 10249,
10250, 10245, 10244, 10241, 10216, 10213, 10212, 10207, 10208, 10201,
10202, 10193, 10194, 10195, 8036, 8033, 8032, 8029, 8028, 8025, 8024, 8021,
7990, 7987, 7986, 7981, 7982, 7971, 7972, 7967, 7966, 7963, 7824, 7821,
7820, 7815, 7816, 7805, 7806, 7801, 7800, 7797, 7766, 7763, 7762, 7757,
7758, 7751, 7752, 7743, 7744, 7745, 7192, 7189, 7188, 7185, 7184, 7181,
7180, 7175, 7176, 7133, 7134, 7129, 7128, 7123, 7124, 7113, 7114, 7107,
7108, 6989, 6990, 6983, 6984, 6973, 6974, 6969, 6968, 6965, 6934, 6931,
6930, 6925, 6926, 6915, 6916, 6911, 6910, 6907, 10402, 10401, 10388, 10387,
10386, 10385, 10264, 10263, 10262, 10261, 10248, 10247, 10246, 10243,
10242, 10215, 10214, 10211, 10210, 10209, 10200, 10199, 10198, 10197,
10196, 8035, 8034, 8031, 8030, 8027, 8026, 8023, 8022, 7989, 7988, 7985,
7984, 7983, 7970, 7969, 7968, 7965, 7964, 7823, 7822, 7819, 7818, 7817,
7804, 7803, 7802, 7799, 7798, 7765, 7764, 7761, 7760, 7759, 7750, 7749,
7748, 7747, 7746, 7191, 7190, 7187, 7186, 7183, 7182, 7179, 7178, 7177,
7132, 7131, 7130, 7127, 7126, 7125, 7112, 7111, 7110, 7109, 6988, 6987,
6986, 6985, 6972, 6971, 6970, 6967, 6966, 6933, 6932, 6929, 6928, 6927,
6914, 6913, 6912, 6909, 6908}.
D14P2 robots is a list of list of numbers that varies.
D14P2 robot positions is a list of numbers that varies.
D14P2 curve positions is a list of numbers that varies.
When D14P2 scene begins:
now D14P2 robots is {};
enable punctuation stripping;
Entering a D14P2 line is an action applying to one topic.
Understand "[text]" as entering a D14P2 line when D14P2 scene is happening.
Carry out entering a D14P2 line:
let words be the the topic understood split by any of {" ", ",", "="};
let robot be a list of numbers;
add entry 2 in words understood as a number to robot;
add entry 3 in words understood as a number to robot;
add entry 5 in words understood as a number to robot;
add entry 6 in words understood as a number to robot;
while entry 3 in robot < 0:
increase entry 3 in robot by D14P2 width;
while entry 4 in robot < 0:
increase entry 4 in robot by D14P2 height;
add robot to D14P2 robots;
[This returns (y * W) + x]
To update the D14P2 robot positions after (step - number) steps:
let result be a list of numbers;
let n be the number of entries in D14P2 robots;
change D14P2 robot positions to have n entries;
repeat with i running from 1 to n:
let px be entry 1 of entry i of D14P2 robots;
let py be entry 2 of entry i of D14P2 robots;
let vx be entry 3 of entry i of D14P2 robots;
let vy be entry 4 of entry i of D14P2 robots;
let nx be the remainder after dividing (px + (vx * step)) by D14P2 width;
let ny be the remainder after dividing (py + (vy * step)) by D14P2 height;
now entry i in D14P2 robot positions is (ny * D14P2 width) + nx;
To decide which number is the D14P2 score:
let n be the number of entries in D14P2 robot positions;
change D14P2 curve positions to have n entries;
repeat with i running from 1 to n:
let robot be entry i in D14P2 robot positions;
now entry i in D14P2 curve positions is entry (robot + 1) of D14P2 gilbert curve;
sort D14P2 curve positions;
let best run be 0;
let current run be 0;
let previous position be -2;
repeat with current position running through D14P2 curve positions:
if current position is previous position + 1:
increment previous position;
increment current run;
else if current position is not previous position:
if current run > best run:
now best run is current run;
now current run is 1;
now previous position is current position;
decide on best run;
To print the D14P2 grid:
sort D14P2 robot positions;
repeat with y running from 1 to D14P2 height:
let line be "";
repeat with x running from 1 to D14P2 width:
if (y * D14P2 width) + x is in already-sorted D14P2 robot positions:
now line is "[line]X";
else:
now line is "[line].";
say "[line][line break]";
To complete the D14P2 calculation:
let n be 0;
let score be 0;
while score < 10:
increment n;
update the D14P2 robot positions after n steps;
now score is the D14P2 score;
log "[n]: [score]" at INFO every 100 of n;
print the D14P2 grid;
say "[n]";
now D14P2 robot positions is {};
now D14P2 curve positions is {};
disable punctuation stripping;
unpush D14P2 button;
Before entering a blank line:
if D14P2 scene is happening:
complete the D14P2 calculation;
Chapter - Day 15
Day 15 is a room.
d15 is a direction. d15 has opposite outside. Index map with d15 mapped as inside.
Door 15 is a door. Door 15 is d15 of the Vortex and outside of Day 15.
Section - Part 1
D15P1 button is a part 1 button.
D15P1 button is here.
D15P1 scene is a recurring scene.
D15P1 scene begins when D15P1 button is switched on.
D15P1 scene ends when D15P1 button is switched off.
Table of Stars (continued)
Day Part Button
15 1 D15P1 button
D15P1 grid entry is a kind of value.
The D15P1 grid entries are D15P1_WALL, D15P1_BOX, D15P1_SPACE.
The D15P1 grid is a list of lists of D15P1 grid entries that varies.
The D15P1 grid width is a number that varies.
The D15P1 grid height is a number that varies.
The D15P1 grid complete is a truth state that varies.
The D15P1 robot X is a number that varies.
The D15P1 robot Y is a number that varies.
When D15P1 scene begins:
now D15P1 grid is {};
now D15P1 grid width is 0;
now D15P1 grid height is 0;
now D15P1 grid complete is false;
now D15P1 robot X is 0;
now D15P1 robot Y is 0;
enable raw input;
After reading a raw input when D15P1 scene is happening:
let line be raw input;
if D15P1 grid complete is false:
if line is "":
now D15P1 grid complete is true;
else:
add line to the D15P1 grid;
else:
if line is "":
complete the D15P1 calculation;
else:
interpret line as D15P1 instructions;
To add (line - text) to the D15P1 grid:
let n be the number of characters in line;
if D15P1 grid width is 0:
now D15P1 grid width is n;
increment D15P1 grid height;
let row be a list of D15P1 grid entry;
repeat with x running from 1 to n:
let c be character number x in line;
if c is "#":
add D15P1_WALL to row;
else if c is ".":
add D15P1_SPACE to row;
else if c is "O":
add D15P1_BOX to row;
else if c is "@":
add D15P1_SPACE to row;
now D15P1 robot X is x;
now D15P1 robot Y is D15P1 grid height;
else:
log "BAD INPUT [c]" at ERROR;
add row to D15P1 grid;
To attempt a D15P1 move of (dx - number) and (dy - number):
let tx be D15P1 robot X + dx;
let ty be D15P1 robot Y + dy;
let nx be tx;
let ny be ty;
while entry nx of entry ny of D15P1 grid is D15P1_BOX:
increase nx by dx;
increase ny by dy;
[
Now (tx, ty) is where we want the robot to move to,
and (nx, ny) is the first non-box space in that direction.
]
if entry nx of entry ny of D15P1 grid is D15P1_SPACE:
[It is possible to move in this direction.]
if tx is not nx or ty is not ny:
[There was a box at (tx, ty) that needs to move to (nx, ny)]
now entry nx of entry ny of D15P1 grid is D15P1_BOX;
now entry tx of entry ty of D15P1 grid is D15P1_SPACE;
now D15P1 robot X is tx;
now D15P1 robot Y is ty;
To interpret (line - text) as D15P1 instructions:
let n be the number of characters in line;
repeat with i running from 1 to n:
let c be character number i in line;
if c is "<":
attempt a D15P1 move of -1 and 0;
else if c is ">":
attempt a D15P1 move of 1 and 0;
else if c is "^":
attempt a D15P1 move of 0 and -1;
else if c is "v":
attempt a D15P1 move of 0 and 1;
To print the D15P1 grid:
repeat with y running from 1 to D15P1 grid height:
let line be "";
repeat with x running from 1 to D15P1 grid width:
let cell be entry x of entry y of D15P1 grid;
let c be "?";
if x is D15P1 robot X and y is D15P1 robot Y:
now c is "@";
else if cell is D15P1_WALL:
now c is "#";
else if cell is D15P1_BOX:
now c is "O";
else if cell is D15P1_SPACE:
now c is ".";
now line is "[line][c]";
say "[line][line break]";
To complete the D15P1 calculation:
let result be 0;
repeat with y running from 1 to D15P1 grid height:
repeat with x running from 1 to D15P1 grid width:
let cell be entry x of entry y of D15P1 grid;
if cell is D15P1_BOX:
let coordinate be ((y - 1) * 100) + (x - 1);
increase result by coordinate;
if result < 0:
log "OVERFLOW" at ERROR;
say "[result][line break]";
disable raw input;
now D15P1 grid is {};
unpush D15P1 button;
Section - Part 2
D15P2 button is a part 2 button.
D15P2 button is here.
D15P2 scene is a recurring scene.
D15P2 scene begins when D15P2 button is switched on.
D15P2 scene ends when D15P2 button is switched off.
Table of Stars (continued)
Day Part Button
15 2 D15P2 button
D15P2 grid entry is a kind of value.
The D15P2 grid entries are D15P2_WALL, D15P2_LEFT_BOX, D15P2_RIGHT_BOX, D15P2_SPACE.
The D15P2 grid is a list of lists of D15P2 grid entries that varies.
The D15P2 grid width is a number that varies.
The D15P2 grid height is a number that varies.
The D15P2 grid complete is a truth state that varies.
The D15P2 robot X is a number that varies.
The D15P2 robot Y is a number that varies.
When D15P2 scene begins:
now D15P2 grid is {};
now D15P2 grid width is 0;
now D15P2 grid height is 0;
now D15P2 grid complete is false;
now D15P2 robot X is 0;
now D15P2 robot Y is 0;
enable raw input;
After reading a raw input when D15P2 scene is happening:
let line be raw input;
if D15P2 grid complete is false:
if line is "":
now D15P2 grid complete is true;
else:
add line to the D15P2 grid;
else:
if line is "":
complete the D15P2 calculation;
else:
interpret line as D15P2 instructions;
To add (line - text) to the D15P2 grid:
let n be the number of characters in line;
if D15P2 grid width is 0:
now D15P2 grid width is n * 2;
increment D15P2 grid height;
let row be a list of D15P2 grid entry;
repeat with x running from 1 to n:
let c be character number x in line;
if c is "#":
add D15P2_WALL to row;
add D15P2_WALL to row;
else if c is ".":
add D15P2_SPACE to row;
add D15P2_SPACE to row;
else if c is "O":
add D15P2_LEFT_BOX to row;
add D15P2_RIGHT_BOX to row;
else if c is "@":
add D15P2_SPACE to row;
add D15P2_SPACE to row;
now D15P2 robot X is (x * 2) - 1;
now D15P2 robot Y is D15P2 grid height;
else:
log "BAD INPUT [c]" at ERROR;
add row to D15P2 grid;
To decide which number is the D15P2 encoded position of (x - number) and (y - number):
decide on ((y - 1) * D15P2 grid width) + x;
To decide which number is the D15P2 unencoded x of (encoded position - number):
decide on (the remainder after dividing (encoded position - 1) by D15P2 grid width) + 1;
To decide which number is the D15P2 unencoded y of (encoded position - number):
decide on ((encoded position - 1) / D15P2 grid width) + 1;
To attempt a D15P2 move of (dx - number) and (dy - number):
let tx be D15P2 robot X + dx;
let ty be D15P2 robot Y + dy;
let moving boxes be a list of numbers;
let check positions be a list of numbers;
let next positions be a list of numbers;
add the D15P2 encoded position of tx and ty to next positions;
while next positions is not empty:
now check positions is next positions;
now next positions is {};
let i be 1;
while i <= number of entries in check positions:
log "[i] [check positions in brace notation]" at INFO;
let pos be entry i in check positions;
let x be the D15P2 unencoded x of pos;
let y be the D15P2 unencoded y of pos;
log "([x],[y])" at INFO;
let cell be entry x of entry y of D15P2 grid;
if cell is D15P2_LEFT_BOX:
add pos to moving boxes;
add the D15P2 encoded position of (x + dx) and (y + dy) to next positions;
[If we're moving the left side of a box, the right also moves]
now pos is the D15P2 encoded position of (x + 1) and y;
if dx is 0 and pos is not listed in check positions:
add pos to check positions;
else if cell is D15P2_RIGHT_BOX:
add pos to moving boxes;
add the D15P2 encoded position of (x + dx) and (y + dy) to next positions;
[If we're moving the right side of a box, the left also moves]
now pos is the D15P2 encoded position of (x - 1) and y;
if dx is 0 and pos is not listed in check positions:
add pos to check positions;
else if cell is D15P2_WALL:
stop;
increment i;
let i be the number of entries in moving boxes;
log "B: [moving boxes in brace notation]" at INFO;
while i >= 1:
let pos be entry i in moving boxes;
let x be the D15P2 unencoded x of pos;
let y be the D15P2 unencoded y of pos;
let cell be entry x of entry y of D15P2 grid;
now entry (x + dx) of entry (y + dy) of D15P2 grid is cell;
now entry x of entry y of D15P2 grid is D15P2_SPACE;
decrement i;
now D15P2 robot X is tx;
now D15P2 robot Y is ty;
To interpret (line - text) as D15P2 instructions:
let n be the number of characters in line;
repeat with i running from 1 to n:
let c be character number i in line;
if c is "<":
attempt a D15P2 move of -1 and 0;
else if c is ">":
attempt a D15P2 move of 1 and 0;
else if c is "^":
attempt a D15P2 move of 0 and -1;
else if c is "v":
attempt a D15P2 move of 0 and 1;
To print the D15P2 grid:
repeat with y running from 1 to D15P2 grid height:
let line be "";
repeat with x running from 1 to D15P2 grid width:
let cell be entry x of entry y of D15P2 grid;
let c be "?";
if x is D15P2 robot X and y is D15P2 robot Y:
now c is "@";
else if cell is D15P2_WALL:
now c is "#";
else if cell is D15P2_LEFT_BOX:
now c is "<";
else if cell is D15P2_RIGHT_BOX:
now c is ">";
else if cell is D15P2_SPACE:
now c is ".";
now line is "[line][c]";
say "[line][line break]";
To complete the D15P2 calculation:
[print the D15P2 grid;]
let result be 0;
repeat with y running from 1 to D15P2 grid height:
repeat with x running from 1 to D15P2 grid width:
let cell be entry x of entry y of D15P2 grid;
if cell is D15P2_LEFT_BOX:
let coordinate be ((y - 1) * 100) + (x - 1);
increase result by coordinate;
if result < 0:
log "OVERFLOW" at ERROR;
say "[result][line break]";
disable raw input;
now D15P2 grid is {};
unpush D15P2 button;
Chapter - Day 16
Day 16 is a room.
d16 is a direction. d16 has opposite outside. Index map with d16 mapped as inside.
Door 16 is a door. Door 16 is d16 of the Vortex and outside of Day 16.
Section - Part 1
D16P1 button is a part 1 button.
D16P1 button is here.
D16P1 scene is a recurring scene.
D16P1 scene begins when D16P1 button is switched on.
D16P1 scene ends when D16P1 button is switched off.
Table of Stars (continued)
Day Part Button
16 1 D16P1 button
The D16P1 grid is a list of text that varies.
The D16P1 grid width is a number that varies.
The D16P1 grid height is a number that varies.
The D16P1 start is a number that varies.
The D16P1 end is a number that varies.
When D16P1 scene begins:
now D16P1 grid is {};
now D16P1 grid width is 0;
now D16P1 grid height is 0;
now D16P1 start is -1;
now D16P1 end is -1;
now D16P1 graph nodes is {};
now D16P1 graph edges is {};
enable raw input;
To decide which number is the D16P1 encoded pose of (position - number) and (orientation - number):
decide on (position * 4) + orientation;
To decide which number is the D16P1 unencoded position of (pose - number):
decide on pose / 4;
To decide which number is the D16P1 unencoded orientation of (pose - number):
decide on the remainder after dividing pose by 4;
To decide which number is the D16P1 encoded position of (x - number) and (y - number):
decide on ((y - 1) * D16P1 grid width) + x;
To decide which number is the D16P1 unencoded x of (encoded position - number):
decide on (the remainder after dividing (encoded position - 1) by D16P1 grid width) + 1;
To decide which number is the D16P1 unencoded y of (encoded position - number):
decide on ((encoded position - 1) / D16P1 grid width) + 1;
After reading a raw input when D16P1 scene is happening:
let line be raw input;
if line is "":
complete the D16P1 calculation;
else:
let n be the number of characters in line;
if D16P1 grid width is 0:
now D16P1 grid width is n;
increment D16P1 grid height;
let y be D16P1 grid height;
add line to the D16P1 grid;
repeat with x running from 1 to n:
let c be character number x in line;
if c is "S":
now D16P1 start is the D16P1 encoded position of x and y;
else if c is "E":
now D16P1 end is the D16P1 encoded position of x and y;
To decide if D16P1 position (x - number) and (y - number) is not a wall:
if character number x in entry y in D16P1 grid is "#", decide no;
decide yes;
D16P1_UP is always 0.
D16P1_LEFT is always 1.
D16P1_DOWN is always 2.
D16P1_RIGHT is always 3.
[pose, ...]
The D16P1 graph nodes is a list of numbers that varies.
[[node index, weight, node index, weight, ...], ...]
The D16P1 graph edges is a list of list of numbers that varies.
To decide which text is D16P1 rendered pose (pose - number):
let position be the D16P1 unencoded position of pose;
let orientation be the D16P1 unencoded orientation of pose;
let d be character number (orientation + 1) in "^<v>";
let x be the D16P1 unencoded x of position;
let y be the D16P1 unencoded y of position;
decide on "([x],[y])[d]";
To precompute the D16P1 graph:
log "Creating graph" at INFO;
let last column positions be a list of numbers;
repeat with x running from 1 to D16P1 grid width:
add -1 to last column positions;
let last row position be -1;
repeat with y running from 1 to D16P1 grid height:
repeat with x running from 1 to D16P1 grid width:
if D16P1 position x and y is not a wall:
let position be the D16P1 encoded position of x and y;
let left be whether or not D16P1 position x - 1 and y is not a wall;
let right be whether or not D16P1 position x + 1 and y is not a wall;
let up be whether or not D16P1 position x and y - 1 is not a wall;
let down be whether or not D16P1 position x and y + 1 is not a wall;
if (
(left is not right) or
(up is not down) or
(left is true and right is true and up is true and down is true) or
(position is D16P1 start) or
(position is D16P1 end)
):
let up pose be the D16P1 encoded pose of position and D16P1_UP;
let right pose be the D16P1 encoded pose of position and D16P1_RIGHT;
let down pose be the D16P1 encoded pose of position and D16P1_DOWN;
let left pose be the D16P1 encoded pose of position and D16P1_LEFT;
[Moving up]
if up is true or down is true:
add up pose to D16P1 graph nodes;
let edges be a list of numbers;
let i be entry x in last column positions;
if up is true and i is not -1:
[If we can move up and there's a node directly above us, connect both ways]
let last position be the D16P1 unencoded position of entry i in D16P1 graph nodes;
let distance be y - (the D16P1 unencoded y of last position);
add the D16P1 encoded pose of last position and D16P1_UP to edges;
add distance to edges;
add down pose to entry i in D16P1 graph edges;
add distance to entry i in D16P1 graph edges;
if right is true:
add right pose to edges;
add 1000 to edges;
if left is true:
add left pose to edges;
add 1000 to edges;
add edges to D16P1 graph edges;
[Moving left]
if left is true or right is true:
add left pose to D16P1 graph nodes;
let edges be a list of numbers;
if left is true and last row position is not -1:
[If we can move left and there's a node directly before us, connect both ways]
let last position be the D16P1 unencoded position of entry last row position in D16P1 graph nodes;
let distance be x - (the D16P1 unencoded x of last position);
add the D16P1 encoded pose of last position and D16P1_LEFT to edges;
add distance to edges;
add right pose to entry last row position in D16P1 graph edges;
add distance to entry last row position in D16P1 graph edges;
if up is true:
add up pose to edges;
add 1000 to edges;
if down is true:
add down pose to edges;
add 1000 to edges;
add edges to D16P1 graph edges;
[Moving down]
if up is true or down is true:
add down pose to D16P1 graph nodes;
let edges be a list of numbers;
if down is true:
now entry x in last column positions is the number of entries in D16P1 graph nodes;
else:
now entry x in last column positions is -1;
if right is true:
add right pose to edges;
add 1000 to edges;
if left is true:
add left pose to edges;
add 1000 to edges;
add edges to D16P1 graph edges;
[Moving right]
if left is true or right is true:
add right pose to D16P1 graph nodes;
let edges be a list of numbers;
if right is true:
now last row position is the number of entries in D16P1 graph nodes;
else:
now last row position is -1;
if up is true:
add up pose to edges;
add 1000 to edges;
if down is true:
add down pose to edges;
add 1000 to edges;
add edges to D16P1 graph edges;
log "Replacing poses with indices" at INFO;
let n be the number of entries in D16P1 graph nodes;
repeat with i running from 1 to n:
let j be 1;
let k be the number of entries in entry i in D16P1 graph edges;
while j <= k:
let pose be entry j in entry i in D16P1 graph edges;
let node index be the lower bound index of pose in D16P1 graph nodes;
if entry node index in D16P1 graph nodes is not pose:
log "FAILED TO INDEX NODE [node index] [D16P1 rendered pose pose] => [pose]/[entry node index in D16P1 graph nodes]" at ERROR;
break;
now entry j in entry i in D16P1 graph edges is node index;
increase j by 2;
To shortcut the D16P1 graph:
let untouchable be a list of numbers;
add the lower bound index of the D16P1 encoded pose of D16P1 start and D16P1_RIGHT in D16P1 graph nodes to untouchable;
let end index be the lower bound index of the D16P1 encoded pose of D16P1 end and 0 in D16P1 graph nodes;
add end index to untouchable;
add end index + 1 to untouchable;
add end index + 2 to untouchable;
add end index + 3 to untouchable;
let found be true;
while found is true:
now found is false;
repeat with a running from 1 to the number of entries in D16P1 graph nodes:
let edges be entry a in D16P1 graph edges;
let i be 1;
while i <= number of entries in edges:
let b be entry i in edges;
while b is not listed in untouchable:
let target edges be entry b in D16P1 graph edges;
if the number of entries in target edges is not 2, break;
now b is entry 1 in target edges;
increase entry i + 1 in edges by entry 2 in target edges;
now found is true;
now entry i in edges is b;
increase i by 2;
now entry a in D16P1 graph edges is edges;
To render the D16P1 graph:
repeat with i running from 1 to the number of entries in D16P1 graph nodes:
let pose be entry i in D16P1 graph nodes;
let edges be entry i in D16P1 graph edges;
let edge renders be a list of text;
let j be 1;
while j <= number of entries in edges:
let node index be entry j in edges;
let dest be entry node index in D16P1 graph nodes;
let cost be entry j + 1 in edges;
add "[D16P1 rendered pose dest] +[cost]" to edge renders;
increase j by 2;
log "[D16P1 rendered pose pose]: [edge renders in brace notation]" at INFO;
[Candidates (score, pose) with threshold - 1000 d score < threshold, unsorted]
D16P1 todo is a list of list of numbers that varies.
To pop the first entry of D16P1 todo:
[Replace the first entry with the last entry]
let n be the number of entries in D16P1 todo;
let v be entry n in D16P1 todo;
now entry 1 in D16P1 todo is v;
remove entry n in D16P1 todo;
decrement n;
[Move nodes down as needed]
let i be 1;
while true is true:
let smallest index be i;
let left index be binary heap left child of i;
let right index be binary heap right child of i;
if left index <= n and entry left index in D16P1 todo < entry smallest index in D16P1 todo:
now smallest index is left index;
if right index <= n and entry right index in D16P1 todo < entry smallest index in D16P1 todo:
now smallest index is right index;
if smallest index is not i:
swap entry i and smallest index in D16P1 todo;
now i is smallest index;
else:
break;
To insert (entry - list of numbers) into D16P1 todo:
add entry to D16P1 todo;
let i be the number of entries in D16P1 todo;
while i > 1:
let j be the binary heap parent of i;
let parent be entry j in D16P1 todo;
if parent <= entry, break;
now entry i in D16P1 todo is parent;
now i is j;
now entry i in D16P1 todo is entry;
To decide which number is the D16P1 estimate of (x - number) and (y - number):
let tx be the D16P1 unencoded x of D16P1 end;
let ty be the D16P1 unencoded y of D16P1 end;
decide on (the integer absolute value of (x - tx)) + (the integer absolute value of (y - ty));
To decide which number is the D16P1 lowest score:
[Visited indices, sorted]
let done be a list of numbers;
[Visited indices, unsorted]
let done buffer be a list of numbers;
add {0, 0} to D16P1 todo;
let pose be the D16P1 encoded pose of D16P1 start and D16P1_RIGHT;
let i be the lower bound index of pose in D16P1 graph nodes;
if entry i in D16P1 graph nodes is not pose:
log "FAILED TO FIND START NODE" at ERROR;
decide on -1;
now entry 2 of entry 1 of D16P1 todo is i;
let end indices be a list of number;
now pose is the D16P1 encoded pose of D16P1 end and 0;
now i is the lower bound index of pose in D16P1 graph nodes;
if entry i in D16P1 graph nodes is not pose:
log "FAILED TO FIND END NODE" at ERROR;
decide on -1;
add i to end indices;
add i + 1 to end indices;
add i + 2 to end indices;
add i + 3 to end indices;
let threshold be 0;
while D16P1 todo is not empty:
let score be entry 1 of entry 1 in D16P1 todo;
if score >= threshold:
log "S: [score] [number of entries in D16P1 todo]" at INFO;
increase threshold by 1000;
let node index be entry 2 of entry 1 in D16P1 todo;
pop the first entry of D16P1 todo;
if node index is listed in end indices:
decide on score;
if node index is in already-sorted done:
next;
if node index is listed in done buffer:
next;
add node index to done buffer;
if the number of entries in done buffer > 100:
sort done buffer;
now done is the unique merge of already-sorted done and done buffer;
now done buffer is {};
let n be the number of entries in entry node index in D16P1 graph edges;
now i is 1;
while i <= n:
let dst be entry i in entry node index in D16P1 graph edges;
let cost be entry i + 1 in entry node index in D16P1 graph edges;
let entry be a list of numbers;
add score + cost to entry;
add dst to entry;
insert entry into D16P1 todo;
increase i by 2;
decide on -1;
To complete the D16P1 calculation:
precompute the D16P1 graph;
log "shortcutting" at INFO;
shortcut the D16P1 graph;
log "computing" at INFO;
let result be D16P1 lowest score;
say "[result][line break]";
disable raw input;
now D16P1 grid is {};
unpush D16P1 button;
Section - Part 2
D16P2 button is a part 2 button.
D16P2 button is here.
D16P2 scene is a recurring scene.
D16P2 scene begins when D16P2 button is switched on.
D16P2 scene ends when D16P2 button is switched off.
Table of Stars (continued)
Day Part Button
16 2 D16P2 button
The D16P2 grid is a list of text that varies.
The D16P2 grid width is a number that varies.
The D16P2 grid height is a number that varies.
The D16P2 start is a number that varies.
The D16P2 end is a number that varies.
When D16P2 scene begins:
now D16P2 grid is {};
now D16P2 grid width is 0;
now D16P2 grid height is 0;
now D16P2 start is -1;
now D16P2 end is -1;
now D16P2 graph nodes is {};
now D16P2 graph edges is {};
enable raw input;
To decide which number is the D16P2 encoded pose of (position - number) and (orientation - number):
decide on (position * 4) + orientation;
To decide which number is the D16P2 unencoded position of (pose - number):
decide on pose / 4;
To decide which number is the D16P2 unencoded orientation of (pose - number):
decide on the remainder after dividing pose by 4;
To decide which number is the D16P2 encoded position of (x - number) and (y - number):
decide on ((y - 1) * D16P2 grid width) + x;
To decide which number is the D16P2 unencoded x of (encoded position - number):
decide on (the remainder after dividing (encoded position - 1) by D16P2 grid width) + 1;
To decide which number is the D16P2 unencoded y of (encoded position - number):
decide on ((encoded position - 1) / D16P2 grid width) + 1;
After reading a raw input when D16P2 scene is happening:
let line be raw input;
if line is "":
complete the D16P2 calculation;
else:
let n be the number of characters in line;
if D16P2 grid width is 0:
now D16P2 grid width is n;
increment D16P2 grid height;
let y be D16P2 grid height;
add line to the D16P2 grid;
repeat with x running from 1 to n:
let c be character number x in line;
if c is "S":
now D16P2 start is the D16P2 encoded position of x and y;
else if c is "E":
now D16P2 end is the D16P2 encoded position of x and y;
To decide if D16P2 position (x - number) and (y - number) is not a wall:
if character number x in entry y in D16P2 grid is "#", decide no;
decide yes;
D16P2_UP is always 0.
D16P2_LEFT is always 1.
D16P2_DOWN is always 2.
D16P2_RIGHT is always 3.
[pose, ...]
The D16P2 graph nodes is a list of numbers that varies.
[[node index, weight, node index, weight, ...], ...]
The D16P2 graph edges is a list of list of numbers that varies.
To decide which text is D16P2 rendered pose (pose - number):
let position be the D16P2 unencoded position of pose;
let orientation be the D16P2 unencoded orientation of pose;
let d be character number (orientation + 1) in "^<v>";
let x be the D16P2 unencoded x of position;
let y be the D16P2 unencoded y of position;
decide on "([x],[y])[d]";
To precompute the D16P2 graph:
log "Creating graph" at INFO;
let last column positions be a list of numbers;
repeat with x running from 1 to D16P2 grid width:
add -1 to last column positions;
let last row position be -1;
repeat with y running from 1 to D16P2 grid height:
repeat with x running from 1 to D16P2 grid width:
if D16P2 position x and y is not a wall:
let position be the D16P2 encoded position of x and y;
let left be whether or not D16P2 position x - 1 and y is not a wall;
let right be whether or not D16P2 position x + 1 and y is not a wall;
let up be whether or not D16P2 position x and y - 1 is not a wall;
let down be whether or not D16P2 position x and y + 1 is not a wall;
if (
(left is not right) or
(up is not down) or
(left is true and right is true and up is true and down is true) or
(position is D16P2 start) or
(position is D16P2 end)
):
let up pose be the D16P2 encoded pose of position and D16P2_UP;
let right pose be the D16P2 encoded pose of position and D16P2_RIGHT;
let down pose be the D16P2 encoded pose of position and D16P2_DOWN;
let left pose be the D16P2 encoded pose of position and D16P2_LEFT;
[Moving up]
if up is true or down is true:
add up pose to D16P2 graph nodes;
let edges be a list of numbers;
let i be entry x in last column positions;
if up is true and i is not -1:
[If we can move up and there's a node directly above us, connect both ways]
let last position be the D16P2 unencoded position of entry i in D16P2 graph nodes;
let distance be y - (the D16P2 unencoded y of last position);
add the D16P2 encoded pose of last position and D16P2_UP to edges;
add distance to edges;
add down pose to entry i in D16P2 graph edges;
add distance to entry i in D16P2 graph edges;
if right is true:
add right pose to edges;
add 1000 to edges;
if left is true:
add left pose to edges;
add 1000 to edges;
add edges to D16P2 graph edges;
[Moving left]
if left is true or right is true:
add left pose to D16P2 graph nodes;
let edges be a list of numbers;
if left is true and last row position is not -1:
[If we can move left and there's a node directly before us, connect both ways]
let last position be the D16P2 unencoded position of entry last row position in D16P2 graph nodes;
let distance be x - (the D16P2 unencoded x of last position);
add the D16P2 encoded pose of last position and D16P2_LEFT to edges;
add distance to edges;
add right pose to entry last row position in D16P2 graph edges;
add distance to entry last row position in D16P2 graph edges;
if up is true:
add up pose to edges;
add 1000 to edges;
if down is true:
add down pose to edges;
add 1000 to edges;
add edges to D16P2 graph edges;
[Moving down]
if up is true or down is true:
add down pose to D16P2 graph nodes;
let edges be a list of numbers;
if down is true:
now entry x in last column positions is the number of entries in D16P2 graph nodes;
else:
now entry x in last column positions is -1;
if right is true:
add right pose to edges;
add 1000 to edges;
if left is true:
add left pose to edges;
add 1000 to edges;
add edges to D16P2 graph edges;
[Moving right]
if left is true or right is true:
add right pose to D16P2 graph nodes;
let edges be a list of numbers;
if right is true:
now last row position is the number of entries in D16P2 graph nodes;
else:
now last row position is -1;
if up is true:
add up pose to edges;
add 1000 to edges;
if down is true:
add down pose to edges;
add 1000 to edges;
add edges to D16P2 graph edges;
log "Replacing poses with indices" at INFO;
let n be the number of entries in D16P2 graph nodes;
repeat with i running from 1 to n:
let j be 1;
let k be the number of entries in entry i in D16P2 graph edges;
while j <= k:
let pose be entry j in entry i in D16P2 graph edges;
let node index be the lower bound index of pose in D16P2 graph nodes;
if entry node index in D16P2 graph nodes is not pose:
log "FAILED TO INDEX NODE [node index] [D16P2 rendered pose pose] => [pose]/[entry node index in D16P2 graph nodes]" at ERROR;
break;
now entry j in entry i in D16P2 graph edges is node index;
increase j by 2;
To shortcut the D16P2 graph:
let untouchable be a list of numbers;
add the lower bound index of the D16P2 encoded pose of D16P2 start and D16P2_RIGHT in D16P2 graph nodes to untouchable;
let end index be the lower bound index of the D16P2 encoded pose of D16P2 end and 0 in D16P2 graph nodes;
add end index to untouchable;
add end index + 1 to untouchable;
add end index + 2 to untouchable;
add end index + 3 to untouchable;
let found be true;
while found is true:
now found is false;
repeat with a running from 1 to the number of entries in D16P2 graph nodes:
let edges be entry a in D16P2 graph edges;
let i be 1;
while i <= number of entries in edges:
let b be entry i in edges;
while b is not listed in untouchable:
let target edges be entry b in D16P2 graph edges;
if the number of entries in target edges is not 2, break;
now b is entry 1 in target edges;
increase entry i + 1 in edges by entry 2 in target edges;
now found is true;
now entry i in edges is b;
increase i by 2;
now entry a in D16P2 graph edges is edges;
To render the D16P2 graph:
repeat with i running from 1 to the number of entries in D16P2 graph nodes:
let pose be entry i in D16P2 graph nodes;
let edges be entry i in D16P2 graph edges;
let edge renders be a list of text;
let j be 1;
while j <= number of entries in edges:
let node index be entry j in edges;
let dest be entry node index in D16P2 graph nodes;
let cost be entry j + 1 in edges;
add "[D16P2 rendered pose dest] +[cost]" to edge renders;
increase j by 2;
log "[D16P2 rendered pose pose]: [edge renders in brace notation]" at INFO;
[Candidates (score, pose) with threshold - 1000 d score < threshold, unsorted]
D16P2 todo is a list of list of numbers that varies.
To pop the first entry of D16P2 todo:
[Replace the first entry with the last entry]
let n be the number of entries in D16P2 todo;
let v be entry n in D16P2 todo;
now entry 1 in D16P2 todo is v;
remove entry n in D16P2 todo;
decrement n;
[Move nodes down as needed]
let i be 1;
while true is true:
let smallest index be i;
let left index be binary heap left child of i;
let right index be binary heap right child of i;
if left index <= n and entry left index in D16P2 todo < entry smallest index in D16P2 todo:
now smallest index is left index;
if right index <= n and entry right index in D16P2 todo < entry smallest index in D16P2 todo:
now smallest index is right index;
if smallest index is not i:
swap entry i and smallest index in D16P2 todo;
now i is smallest index;
else:
break;
To insert (entry - list of numbers) into D16P2 todo:
add entry to D16P2 todo;
let i be the number of entries in D16P2 todo;
while i > 1:
let j be the binary heap parent of i;
let parent be entry j in D16P2 todo;
if parent <= entry, break;
now entry i in D16P2 todo is parent;
now i is j;
now entry i in D16P2 todo is entry;
To decide which number is the D16P2 estimate of (x - number) and (y - number):
let tx be the D16P2 unencoded x of D16P2 end;
let ty be the D16P2 unencoded y of D16P2 end;
decide on (the integer absolute value of (x - tx)) + (the integer absolute value of (y - ty));
To decide which number is the D16P2 lowest score:
let best distances be a list of numbers;
let best parents be a list of list of numbers;
repeat with i running from 1 to the number of entries in D16P2 graph nodes:
add MAX_I32 to best distances;
let parents be a list of numbers;
add parents to best parents;
add {0, 0, 0} to D16P2 todo;
let pose be the D16P2 encoded pose of D16P2 start and D16P2_RIGHT;
let i be the lower bound index of pose in D16P2 graph nodes;
if entry i in D16P2 graph nodes is not pose:
log "FAILED TO FIND START NODE" at ERROR;
decide on -1;
now entry 2 of entry 1 of D16P2 todo is i;
let end indices be a list of number;
now pose is the D16P2 encoded pose of D16P2 end and 0;
now i is the lower bound index of pose in D16P2 graph nodes;
if entry i in D16P2 graph nodes is not pose:
log "FAILED TO FIND END NODE" at ERROR;
decide on -1;
add i to end indices;
add i + 1 to end indices;
add i + 2 to end indices;
add i + 3 to end indices;
let threshold be 0;
let best path length be -1;
while D16P2 todo is not empty:
let score be entry 1 of entry 1 in D16P2 todo;
if score >= threshold:
log "S: [score] [number of entries in D16P2 todo]" at INFO;
increase threshold by 1000;
let node index be entry 2 of entry 1 in D16P2 todo;
let parent be entry 3 of entry 1 in D16P2 todo;
pop the first entry of D16P2 todo;
if best path length is -1:
if node index is listed in end indices:
log "FOUND END" at INFO;
now best path length is score;
else if score > best path length:
log "END: [score] > [best path length]" at INFO;
break;
if score > entry node index in best distances:
next;
if score is entry node index in best distances:
if parent is not listed in entry node index in best parents:
add parent to entry node index in best parents;
next;
now entry node index in best distances is score;
now entry node index in best parents is {};
add parent to entry node index in best parents;
let n be the number of entries in entry node index in D16P2 graph edges;
now i is 1;
while i <= n:
let dst be entry i in entry node index in D16P2 graph edges;
let cost be entry i + 1 in entry node index in D16P2 graph edges;
let entry be a list of numbers;
add score + cost to entry;
add dst to entry;
add node index to entry;
insert entry into D16P2 todo;
increase i by 2;
log "Expanding best paths" at INFO;
now D16P2 todo is {};
let best positions be a list of numbers;
let todo be end indices;
while todo is not empty:
let n be the number of entries in todo;
let node index be entry n in todo;
truncate todo to n - 1 entries;
let pose be entry node index in D16P2 graph nodes;
let position be the D16P2 unencoded position of pose;
let ax be the D16P2 unencoded x of position;
let ay be the D16P2 unencoded y of position;
repeat with parent index running through entry node index in best parents:
if parent index is 0, next;
let parent pose be entry parent index in D16P2 graph nodes;
let parent position be D16P2 unencoded position of parent pose;
let bx be the D16P2 unencoded x of parent position;
let by be the D16P2 unencoded y of parent position;
if ax is not bx and ay is not by:
log "BAD SHORTCUT: ([ax],[ay]) -> ([bx],[by])" at ERROR;
decide on -1;
add (the D16P2 positions from ax and ay to bx and by) to best positions;
add parent index to todo;
now entry node index in best parents is {};
sort best positions;
decide on the distinct count of already-sorted best positions;
To decide which list of numbers is the D16P2 positions from (ax - number) and (ay - number) to (bx - number) and (by - number):
if bx < ax:
let tmp be ax;
now ax is bx;
now bx is tmp;
if by < ay:
let tmp be ay;
now ay is by;
now by is tmp;
let result be a list of numbers;
repeat with y running from ay to by:
repeat with x running from ax to bx:
add the D16P2 encoded position of x and y to result;
decide on result;
To complete the D16P2 calculation:
precompute the D16P2 graph;
log "shortcutting" at INFO;
shortcut the D16P2 graph;
log "computing" at INFO;
let result be D16P2 lowest score;
say "[result][line break]";
disable raw input;
now D16P2 grid is {};
unpush D16P2 button;
Chapter - Day 17
Day 17 is a room.
d17 is a direction. d17 has opposite outside. Index map with d17 mapped as inside.
Door 17 is a door. Door 17 is d17 of the Vortex and outside of Day 17.
Section - Part 1
D17P1 button is a part 1 button.
D17P1 button is here.
D17P1 scene is a recurring scene.
D17P1 scene begins when D17P1 button is switched on.
D17P1 scene ends when D17P1 button is switched off.
Table of Stars (continued)
Day Part Button
17 1 D17P1 button
D17P1 Register A is a number that varies.
D17P1 Register B is a number that varies.
D17P1 Register C is a number that varies.
When D17P1 scene begins:
enable raw input;
After reading a raw input when D17P1 scene is happening:
let words be the words of raw input;
if words is empty, stop;
if entry 1 of words exactly matches the text "register", case insensitively:
let register be entry 2 in words;
let v be entry 3 in words;
if register exactly matches the text "a", case insensitively:
now D17P1 register A is v understood as a number;
else if register exactly matches the text "b", case insensitively:
now D17P1 register B is v understood as a number;
else if register exactly matches the text "c", case insensitively:
now D17P1 register C is v understood as a number;
else:
log "UNKNOWN REGISTER [register]" at ERROR;
else if entry 1 of words exactly matches the text "program", case insensitively:
let instructions be a list of numbers;
let n be the number of entries in words;
repeat with i running from 2 to n:
add entry i in words understood as a number to instructions;
compute the D17P1 program instructions;
To decide what number is the D17P1 combo (operand - number):
if operand is 4:
decide on D17P1 Register A;
if operand is 5:
decide on D17P1 Register B;
if operand is 6:
decide on D17P1 Register C;
decide on operand;
To compute the D17P1 program (instructions - list of numbers):
let instruction pointer be 1;
let n be the number of entries in instructions;
let output be "";
while instruction pointer <= n:
let opcode be entry instruction pointer in instructions;
let operand be entry instruction pointer + 1 in instructions;
if opcode is 0:
now D17P1 Register A is D17P1 Register A / (2 to the power of the D17P1 combo operand);
else if opcode is 1:
now D17P1 Register B is D17P1 Register B xor operand;
else if opcode is 2:
now D17P1 Register B is the remainder after dividing the D17P1 combo operand by 8;
else if opcode is 3:
if D17P1 Register A is not 0:
now instruction pointer is operand - 1;
else if opcode is 4:
now D17P1 Register B is D17P1 Register B xor D17P1 Register C;
else if opcode is 5:
let v be the remainder after dividing the D17P1 combo operand by 8;
log "OUT: [v]" at INFO;
if output is "":
now output is "[v]";
else:
now output is "[output],[v]";
else if opcode is 6:
now D17P1 Register B is D17P1 Register A / (2 to the power of the D17P1 combo operand);
else if opcode is 7:
now D17P1 Register C is D17P1 Register A / (2 to the power of the D17P1 combo operand);
log "op=[opcode] A=[D17P1 Register A] B=[D17P1 Register B] C=[D17P1 Register C]" at INFO;
increase instruction pointer by 2;
say "[output][line break]";
disable raw input;
unpush D17P1 button;
Section - Part 2
D17P2 button is a part 2 button.
D17P2 button is here.
D17P2 scene is a recurring scene.
D17P2 scene begins when D17P2 button is switched on.
D17P2 scene ends when D17P2 button is switched off.
Table of Stars (continued)
Day Part Button
17 2 D17P2 button
D17P2 Register A is a list of number that varies.
D17P2 Register B is a list of number that varies.
D17P2 Register C is a list of number that varies.
D17P2 Program is a list of numbers that varies.
When D17P2 scene begins:
enable raw input;
After reading a raw input when D17P2 scene is happening:
let words be the words of raw input;
if words is empty, stop;
if entry 1 of words exactly matches the text "program", case insensitively:
let instructions be a list of numbers;
let n be the number of entries in words;
repeat with i running from 2 to n:
add entry i in words understood as a number to instructions;
now D17P2 program is instructions;
complete the D17P2 calculation;
To decide what number is the D17P2 combo (operand - number):
if operand is 4:
decide on entry 2 in D17P2 Register A;
if operand is 5:
decide on entry 2 in D17P2 Register B;
if operand is 6:
decide on entry 2 in D17P2 Register C;
decide on operand;
To decide what list of numbers is the D17P2 program run with (a - list of number):
now D17P2 Register A is a;
now D17P2 Register B is BIGNUM_ZERO;
now D17P2 Register C is BIGNUM_ZERO;
let output be a list of numbers;
let instruction pointer be 1;
let n be the number of entries in D17P2 program;
while instruction pointer <= n:
let opcode be entry instruction pointer in D17P2 program;
let operand be entry instruction pointer + 1 in D17P2 program;
if opcode is 0:
now D17P2 Register A is D17P2 Register A bignum>> the D17P2 combo operand;
else if opcode is 1:
now D17P2 Register B is D17P2 Register B bignum^ (operand converted to bignum);
else if opcode is 2:
now D17P2 Register B is (the remainder after dividing the D17P2 combo operand by 8) converted to bignum;
else if opcode is 3:
if D17P2 Register A is not BIGNUM_ZERO:
now instruction pointer is operand - 1;
else if opcode is 4:
now D17P2 Register B is D17P2 Register B bignum^ D17P2 Register C;
else if opcode is 5:
let v be the remainder after dividing the D17P2 combo operand by 8;
add v to output;
else if opcode is 6:
now D17P2 Register B is D17P2 Register A bignum>> the D17P2 combo operand;
else if opcode is 7:
now D17P2 Register C is D17P2 Register A bignum>> the D17P2 combo operand;
increase instruction pointer by 2;
decide on output;
To decide what list of number is the D17P2 quine with (base - list of number) at (n - number):
if n < 0, decide on base;
let target be entry n + 1 in D17P2 Program;
repeat with i running from 0 to 7:
let a be base bignum+ ((i converted to bignum) bignum<< (n * 3));
let output be the D17P2 program run with a;
if the number of entries in output > n and entry n + 1 in output is target:
let rv be the D17P2 quine with a at (n - 1);
if rv is not empty, decide on rv;
decide on {};
To decide what list of number is the D17P2 quine:
let n be the number of entries in D17P2 Program;
repeat with i running from 0 to 15:
let a be (i converted to bignum) bignum<< (n * 3);
let rv be the D17P2 quine with a at (n - 1);
if rv is not empty, decide on rv;
decide on {};
To complete the D17P2 calculation:
say "[the D17P2 quine in bignum notation][line break]";
disable raw input;
unpush D17P2 button;
Chapter - Day 18
Day 18 is a room.
d18 is a direction. d18 has opposite outside. Index map with d18 mapped as inside.
Door 18 is a door. Door 18 is d18 of the Vortex and outside of Day 18.
Section - Part 1
D18P1 button is a part 1 button.
D18P1 button is here.
D18P1 scene is a recurring scene.
D18P1 scene begins when D18P1 button is switched on.
D18P1 scene ends when D18P1 button is switched off.
Table of Stars (continued)
Day Part Button
18 1 D18P1 button
D18P1 grid is a list of list of numbers that varies.
D18P1 grid width is always 71.
D18P1 grid height is always 71.
D18P1 end x is a number that varies.
D18P1 end y is a number that varies.
D18P1 order is a number that varies.
D18P1 todo is a list of list of numbers that varies.
When D18P1 scene begins:
enable punctuation stripping;
now D18P1 todo is {};
now D18P1 grid is {};
repeat with y running from 1 to D18P1 grid height:
let row be a list of numbers;
repeat with x running from 1 to D18P1 grid width:
add MAX_I32 to row;
add row to D18P1 grid;
now D18P1 end x is 0;
now D18P1 end y is 0;
now D18P1 order is 1;
Entering a D18P1 line is an action applying to one topic.
Understand "[text]" as entering a D18P1 line while D18P1 scene is happening.
Carry out entering a D18P1 line:
let words be the words of the topic understood;
let x be entry 1 in words understood as a number;
let y be entry 2 in words understood as a number;
if x > D18P1 end x:
now D18P1 end x is x;
if y > D18P1 end y:
now D18P1 end y is y;
now entry (x + 1) in entry (y + 1) in D18P1 grid is D18P1 order;
increment D18P1 order;
[D18P1 simulated steps is always 12.]
D18P1 simulated steps is always 1024.
To pop the first entry of D18P1 todo:
[Replace the first entry with the last entry]
let n be the number of entries in D18P1 todo;
let v be entry n in D18P1 todo;
now entry 1 in D18P1 todo is v;
remove entry n in D18P1 todo;
decrement n;
[Move nodes down as needed]
let i be 1;
while true is true:
let smallest index be i;
let left index be binary heap left child of i;
let right index be binary heap right child of i;
if left index <= n and entry left index in D18P1 todo < entry smallest index in D18P1 todo:
now smallest index is left index;
if right index <= n and entry right index in D18P1 todo < entry smallest index in D18P1 todo:
now smallest index is right index;
if smallest index is not i:
swap entry i and smallest index in D18P1 todo;
now i is smallest index;
else:
break;
To insert (entry - list of numbers) into D18P1 todo:
add entry to D18P1 todo;
let i be the number of entries in D18P1 todo;
while i > 1:
let j be the binary heap parent of i;
let parent be entry j in D18P1 todo;
if parent <= entry, break;
now entry i in D18P1 todo is parent;
now i is j;
now entry i in D18P1 todo is entry;
To decide which number is the D18P1 shortest path:
log "[D18P1 grid in brace notation]" at INFO;
[(#steps + estimated distance left, #steps, x, y), ...]
let initial entry be a list of numbers;
add D18P1 end x + D18P1 end y to initial entry;
add 0 to initial entry;
add 0 to initial entry;
add 0 to initial entry;
add initial entry to D18P1 todo;
while D18P1 todo is not empty:
let item be entry 1 in D18P1 todo;
log "I: [item in brace notation]" at INFO;
let steps be entry 2 in item;
let x be entry 3 in item;
let y be entry 4 in item;
pop the first entry of D18P1 todo;
if x is D18P1 end x and y is D18P1 end y:
decide on steps;
increment steps;
if x > 0 and entry x in entry (y + 1) in D18P1 grid > D18P1 simulated steps:
let new item be a list of numbers;
add (steps + the manhattan distance from x - 1 and y to D18P1 end x and D18P1 end y) to new item;
add steps to new item;
add x - 1 to new item;
add y to new item;
log " -R> [new item in brace notation]" at INFO;
insert new item into D18P1 todo;
now entry x in entry (y + 1) in D18P1 grid is 0;
if x < D18P1 end x and entry (x + 2) in entry (y + 1) in D18P1 grid > D18P1 simulated steps:
let new item be a list of numbers;
add (steps + the manhattan distance from x + 1 and y to D18P1 end x and D18P1 end y) to new item;
add steps to new item;
add x + 1 to new item;
add y to new item;
log " -L> [new item in brace notation]" at INFO;
insert new item into D18P1 todo;
now entry (x + 2) in entry (y + 1) in D18P1 grid is 0;
if y > 0 and entry (x + 1) in entry y in D18P1 grid > D18P1 simulated steps:
let new item be a list of numbers;
add (steps + the manhattan distance from x and y - 1 to D18P1 end x and D18P1 end y) to new item;
add steps to new item;
add x to new item;
add y - 1 to new item;
log " -U> [new item in brace notation]" at INFO;
insert new item into D18P1 todo;
now entry (x + 1) in entry y in D18P1 grid is 0;
if y < D18P1 end y and entry (x + 1) in entry (y + 2) in D18P1 grid > D18P1 simulated steps:
let new item be a list of numbers;
add (steps + the manhattan distance from x and y + 1 to D18P1 end x and D18P1 end y) to new item;
add steps to new item;
add x to new item;
add y + 1 to new item;
log " -D> [new item in brace notation]" at INFO;
insert new item into D18P1 todo;
now entry (x + 1) in entry (y + 2) in D18P1 grid is 0;
decide on -1;
To complete the D18P1 computation:
let result be the D18P1 shortest path;
say result;
disable punctuation stripping;
now D18P1 todo is {};
now D18P1 grid is {};
unpush D18P1 button;
Before entering a blank line:
if D18P1 scene is happening:
complete the D18P1 computation instead;
Section - Part 2
D18P2 button is a part 2 button.
D18P2 button is here.
D18P2 scene is a recurring scene.
D18P2 scene begins when D18P2 button is switched on.
D18P2 scene ends when D18P2 button is switched off.
Table of Stars (continued)
Day Part Button
18 2 D18P2 button
D18P2 grid is a list of list of numbers that varies.
D18P2 grid width is always 71.
D18P2 grid height is always 71.
D18P2 end x is a number that varies.
D18P2 end y is a number that varies.
D18P2 order is a number that varies.
D18P2 todo is a list of list of numbers that varies.
When D18P2 scene begins:
enable punctuation stripping;
now D18P2 grid is {};
repeat with y running from 1 to D18P2 grid height:
let row be a list of numbers;
repeat with x running from 1 to D18P2 grid width:
add MAX_I32 to row;
add row to D18P2 grid;
now D18P2 end x is 0;
now D18P2 end y is 0;
now D18P2 order is 1;
Entering a D18P2 line is an action applying to one topic.
Understand "[text]" as entering a D18P2 line while D18P2 scene is happening.
Carry out entering a D18P2 line:
let words be the words of the topic understood;
let x be entry 1 in words understood as a number;
let y be entry 2 in words understood as a number;
if x > D18P2 end x:
now D18P2 end x is x;
if y > D18P2 end y:
now D18P2 end y is y;
now entry (x + 1) in entry (y + 1) in D18P2 grid is D18P2 order;
increment D18P2 order;
To pop the first entry of D18P2 todo:
[Replace the first entry with the last entry]
let n be the number of entries in D18P2 todo;
let v be entry n in D18P2 todo;
now entry 1 in D18P2 todo is v;
remove entry n in D18P2 todo;
decrement n;
[Move nodes down as needed]
let i be 1;
while true is true:
let smallest index be i;
let left index be binary heap left child of i;
let right index be binary heap right child of i;
if left index <= n and entry left index in D18P2 todo < entry smallest index in D18P2 todo:
now smallest index is left index;
if right index <= n and entry right index in D18P2 todo < entry smallest index in D18P2 todo:
now smallest index is right index;
if smallest index is not i:
swap entry i and smallest index in D18P2 todo;
now i is smallest index;
else:
break;
To insert (entry - list of numbers) into D18P2 todo:
add entry to D18P2 todo;
let i be the number of entries in D18P2 todo;
while i > 1:
let j be the binary heap parent of i;
let parent be entry j in D18P2 todo;
if parent <= entry, break;
now entry i in D18P2 todo is parent;
now i is j;
now entry i in D18P2 todo is entry;
To decide which number is the D18P2 encoded position of (x - number) and (y - number):
decide on (y * D18P2 grid height) + x;
To decide which number is the D18P2 shortest path with (simulated steps - number):
log "trying with [simulated steps]" at INFO;
now D18P2 todo is {};
[(#steps + estimated distance left, #steps, x, y), ...]
let initial entry be a list of numbers;
add D18P2 end x + D18P2 end y to initial entry;
add 0 to initial entry;
add 0 to initial entry;
add 0 to initial entry;
add initial entry to D18P2 todo;
let sorted done be a list of numbers;
let unsorted done be a list of numbers;
while D18P2 todo is not empty:
let item be entry 1 in D18P2 todo;
let steps be entry 2 in item;
let x be entry 3 in item;
let y be entry 4 in item;
pop the first entry of D18P2 todo;
if x is D18P2 end x and y is D18P2 end y:
log "=> SUCCESS" at INFO;
decide on steps;
let position be the D18P2 encoded position of x and y;
if position is in already-sorted sorted done:
next;
if position is listed in unsorted done:
next;
add the D18P2 encoded position of x and y to unsorted done;
if the number of entries in unsorted done > 100:
sort unsorted done;
now sorted done is the merge of already-sorted sorted done and unsorted done;
now unsorted done is {};
increment steps;
if x > 0 and entry x in entry (y + 1) in D18P2 grid > simulated steps:
let new item be a list of numbers;
add (steps + the manhattan distance from x - 1 and y to D18P2 end x and D18P2 end y) to new item;
add steps to new item;
add x - 1 to new item;
add y to new item;
insert new item into D18P2 todo;
if x < D18P2 end x and entry (x + 2) in entry (y + 1) in D18P2 grid > simulated steps:
let new item be a list of numbers;
add (steps + the manhattan distance from x + 1 and y to D18P2 end x and D18P2 end y) to new item;
add steps to new item;
add x + 1 to new item;
add y to new item;
insert new item into D18P2 todo;
if y > 0 and entry (x + 1) in entry y in D18P2 grid > simulated steps:
let new item be a list of numbers;
add (steps + the manhattan distance from x and y - 1 to D18P2 end x and D18P2 end y) to new item;
add steps to new item;
add x to new item;
add y - 1 to new item;
insert new item into D18P2 todo;
if y < D18P2 end y and entry (x + 1) in entry (y + 2) in D18P2 grid > simulated steps:
let new item be a list of numbers;
add (steps + the manhattan distance from x and y + 1 to D18P2 end x and D18P2 end y) to new item;
add steps to new item;
add x to new item;
add y + 1 to new item;
insert new item into D18P2 todo;
log " => FAIL" at INFO;
decide on -1;
To decide which number is the D18P2 blocking index:
let low be 0;
let length be D18P2 order;
while length > 0:
let half length be length / 2;
let mid be low + half length;
if the D18P2 shortest path with (mid + 1) is not -1:
now low is mid + 1;
now length is length - (half length + 1);
otherwise:
now length is half length;
decide on (low + 1).
To say the D18P2 coordinate at (index - number):
repeat with y running from 0 to D18P2 end y:
repeat with x running from 0 to D18P2 end x:
if entry (x + 1) in entry (y + 1) in D18P2 grid is index:
say "[x],[y]";
stop;
To complete the D18P2 computation:
let result be the D18P2 blocking index;
say the D18P2 coordinate at result;
disable punctuation stripping;
now D18P2 todo is {};
now D18P2 grid is {};
unpush D18P2 button;
Before entering a blank line:
if D18P2 scene is happening:
complete the D18P2 computation instead;
Chapter - Day 19
Day 19 is a room.
d19 is a direction. d19 has opposite outside. Index map with d19 mapped as inside.
Door 19 is a door. Door 19 is d19 of the Vortex and outside of Day 19.
Section - Part 1
D19P1 button is a part 1 button.
D19P1 button is here.
D19P1 scene is a recurring scene.
D19P1 scene begins when D19P1 button is switched on.
D19P1 scene ends when D19P1 button is switched off.
Table of Stars (continued)
Day Part Button
19 1 D19P1 button
[
First, we remap the colours to numbers:
1 w white
2 u blue
3 b black
4 r red
5 g green
]
To decide which number is the D19P1 colour remap of (c - text):
if c is "w", decide on 1;
if c is "u", decide on 2;
if c is "b", decide on 3;
if c is "r", decide on 4;
if c is "g", decide on 5;
log "BAD COLOUR: [c]" at ERROR;
decide on 0;
[
Each patch is therefore a list of numbers, e.g. ubwu => {2, 3, 1, 2}
]
To decide which list of numbers is the D19P1 patch remap of (patch - text):
let result be a list of numbers;
let n be the number of characters in patch;
repeat with i running from 1 to n:
add the D19P1 colour remap of character number i in patch to result;
decide on result;
[
This stores the patches, indexed by their first colour, and sorted by length.
]
D19P1 available patches is a list of list of list of numbers that varies.
D19P1 result is a number that varies.
When D19P1 scene begins:
now D19P1 available patches is {};
now D19P1 result is 0;
repeat with i running from 1 to 5:
let patches be a list of list of numbers;
add patches to D19P1 available patches;
read the D19P1 available patches;
[Discard a blank line.]
read raw input;
enable raw input;
To decide what number is the D19P1 available patch sort order between (x - list of numbers) and (y - list of numbers) (this is D19P1 length):
decide on the number of entries in x - the number of entries in y;
To read the D19P1 available patches:
read raw input;
let patches be the raw input split by any of {",", " "};
repeat with p running through patches:
let r be the D19P1 patch remap of p;
let index be entry 1 in r;
add r to entry index in D19P1 available patches;
repeat with i running from 1 to 5:
sort entry i in D19P1 available patches by D19P1 length;
log "[D19P1 available patches in brace notation]" at INFO;
[#characters left, ...]
D19P1 todo is a list of numbers that varies.
To pop the first entry of D19P1 todo:
[Replace the first entry with the last entry]
let n be the number of entries in D19P1 todo;
let v be entry n in D19P1 todo;
now entry 1 in D19P1 todo is v;
remove entry n in D19P1 todo;
decrement n;
[Move nodes down as needed]
let i be 1;
while true is true:
let smallest index be i;
let left index be binary heap left child of i;
let right index be binary heap right child of i;
if left index <= n and entry left index in D19P1 todo < entry smallest index in D19P1 todo:
now smallest index is left index;
if right index <= n and entry right index in D19P1 todo < entry smallest index in D19P1 todo:
now smallest index is right index;
if smallest index is not i:
swap entry i and smallest index in D19P1 todo;
now i is smallest index;
else:
break;
To insert (entry - number) into D19P1 todo:
add entry to D19P1 todo;
let i be the number of entries in D19P1 todo;
while i > 1:
let j be the binary heap parent of i;
let parent be entry j in D19P1 todo;
if parent <= entry, break;
now entry i in D19P1 todo is parent;
now i is j;
now entry i in D19P1 todo is entry;
To decide if D19P1 patch (p - text) is valid:
let r be the D19P1 patch remap of p;
log "P: [r in brace notation]" at INFO;
now D19P1 todo is {};
let n be the number of entries in r;
add n to D19P1 todo;
let done be a list of truth states;
repeat with i running from 1 to n:
add false to done;
now entry n in done is true;
while D19P1 todo is not empty:
let x be entry 1 in D19P1 todo;
pop the first entry of D19P1 todo;
log "E: [x]" at INFO;
let index be entry n - x + 1 in r;
let m be the number of entries in entry index in D19P1 available patches;
repeat with i running from 1 to m:
log " -> [entry i in entry index in D19P1 available patches in brace notation]" at INFO;
let patch length be the number of entries in entry i in entry index in D19P1 available patches;
[If this patch is longer than what we have left, no further patches will match, since we're sorted by length.]
if patch length > x:
break;
[If this patch would take use to a state we've already been to, skip it]
let y be x - patch length;
if y > 0 and entry y in done is true:
next;
[Check if this patch matches the input. We know the first one matches, so start from 2.]
let matches be true;
repeat with j running from 2 to patch length:
if entry n - x + j in r is not entry j in entry i in entry index in D19P1 available patches:
now matches is false;
break;
if matches is false:
next;
if y is 0, decide yes;
insert y into D19P1 todo;
now entry y in done is true;
decide no;
After reading a raw input when D19P1 scene is happening:
let p be the raw input;
if p is "":
complete the D19P1 computation;
else if D19P1 patch p is valid:
increment D19P1 result;
say "Y";
else:
say "N";
To complete the D19P1 computation:
now D19P1 todo is {};
say "[D19P1 result]";
disable raw input;
unpush D19P1 button;
Section - Part 2
D19P2 button is a part 2 button.
D19P2 button is here.
D19P2 scene is a recurring scene.
D19P2 scene begins when D19P2 button is switched on.
D19P2 scene ends when D19P2 button is switched off.
Table of Stars (continued)
Day Part Button
19 2 D19P2 button
[
First, we remap the colours to numbers:
1 w white
2 u blue
3 b black
4 r red
5 g green
]
To decide which number is the D19P2 colour remap of (c - text):
if c is "w", decide on 1;
if c is "u", decide on 2;
if c is "b", decide on 3;
if c is "r", decide on 4;
if c is "g", decide on 5;
log "BAD COLOUR: [c]" at ERROR;
decide on 0;
[
Each patch is therefore a list of numbers, e.g. ubwu => {2, 3, 1, 2}
]
To decide which list of numbers is the D19P2 patch remap of (patch - text):
let result be a list of numbers;
let n be the number of characters in patch;
repeat with i running from 1 to n:
add the D19P2 colour remap of character number i in patch to result;
decide on result;
[
This stores the patches, indexed by their first colour, and sorted by length.
]
D19P2 available patches is a list of list of list of numbers that varies.
D19P2 result is a list of numbers that varies.
When D19P2 scene begins:
now D19P2 available patches is {};
now D19P2 result is BIGNUM_ZERO;
repeat with i running from 1 to 5:
let patches be a list of list of numbers;
add patches to D19P2 available patches;
read the D19P2 available patches;
[Discard a blank line.]
read raw input;
enable raw input;
To decide what number is the D19P2 available patch sort order between (x - list of numbers) and (y - list of numbers) (this is D19P2 length):
decide on the number of entries in x - the number of entries in y;
To read the D19P2 available patches:
read raw input;
let patches be the raw input split by any of {",", " "};
repeat with p running through patches:
let r be the D19P2 patch remap of p;
let index be entry 1 in r;
add r to entry index in D19P2 available patches;
repeat with i running from 1 to 5:
sort entry i in D19P2 available patches by D19P2 length;
log "[D19P2 available patches in brace notation]" at INFO;
To decide which list of number is the combinations of D19P2 patch (p - text):
let r be the D19P2 patch remap of p;
log "P: [r in brace notation]" at INFO;
let n be the number of entries in r;
[entry i is the number of ways to make the patch starting at entry i]
let ways be a list of list of numbers;
repeat with i running from 1 to n:
add BIGNUM_ZERO to ways;
add BIGNUM_ONE to ways;
let i be n;
while i >= 1:
let index be entry i in r;
let m be the number of entries in entry index in D19P2 available patches;
repeat with j running from 1 to m:
let patch length be the number of entries in entry j in entry index in D19P2 available patches;
[If this patch is longer than what we have left, no further patches will match, since we're sorted by length.]
if patch length > n - i + 1:
break;
[Check if this patch matches the input. We know the first one matches, so start from 2.]
let matches be true;
repeat with k running from 2 to patch length:
if entry i + k - 1 in r is not entry k in entry j in entry index in D19P2 available patches:
now matches is false;
break;
if matches is false:
next;
now entry i in ways is entry i in ways bignum+ entry i + patch length in ways;
decrement i;
decide on entry 1 in ways;
After reading a raw input when D19P2 scene is happening:
let p be the raw input;
if p is "":
complete the D19P2 computation;
else:
now D19P2 result is D19P2 result bignum+ the combinations of D19P2 patch p;
To complete the D19P2 computation:
say "[D19P2 result in bignum notation]";
disable raw input;
unpush D19P2 button;
Chapter - Day 20
Day 20 is a room.
d20 is a direction. d20 has opposite outside. Index map with d20 mapped as inside.
Door 20 is a door. Door 20 is d20 of the Vortex and outside of Day 20.
Section - Part 1
D20P1 button is a part 1 button.
D20P1 button is here.
D20P1 scene is a recurring scene.
D20P1 scene begins when D20P1 button is switched on.
D20P1 scene ends when D20P1 button is switched off.
Table of Stars (continued)
Day Part Button
20 1 D20P1 button
D20P1 grid is a list of list of numbers that varies.
D20P1 grid width is a number that varies.
D20P1 grid height is a number that varies.
D20P1 start x is a number that varies.
D20P1 start y is a number that varies.
D20P1 end x is a number that varies.
D20P1 end y is a number that varies.
When D20P1 scene begins:
enable raw input;
now D20P1 grid is {};
now D20P1 grid width is 0;
now D20P1 grid height is 0;
To add (line - text) to the D20P1 grid:
let n be the number of characters in line;
if D20P1 grid width is 0:
now D20P1 grid width is n;
increment D20P1 grid height;
let row be a list of numbers;
repeat with x running from 1 to n:
let c be character number x in line;
if c is "#":
add -1 to row;
else if c is ".":
add 0 to row;
else if c is "S":
add 0 to row;
now D20P1 start x is x;
now D20P1 start y is D20P1 grid height;
else if c is "E":
add 0 to row;
now D20P1 end x is x;
now D20P1 end y is D20P1 grid height;
else:
log "BAD GRID CHARACTER: [c]" at ERROR;
add row to D20P1 grid;
After reading a raw input when D20P1 scene is happening:
let line be the raw input;
if line is "":
complete the D20P1 computation;
else:
add line to the D20P1 grid;
To trace the D20P1 race track:
let x be D20P1 start x;
let y be D20P1 start y;
let step be 1;
while x is not D20P1 end x or y is not D20P1 end y:
now entry x in entry y in D20P1 grid is step;
increment step;
if x > 1 and entry x - 1 in entry y in D20P1 grid is 0:
decrement x;
else if x < D20P1 grid width and entry x + 1 in entry y in D20P1 grid is 0:
increment x;
else if y > 1 and entry x in entry y - 1 in D20P1 grid is 0:
decrement y;
else if y < D20P1 grid height and entry x in entry y + 1 in D20P1 grid is 0:
increment y;
else:
log "FAILED TO TRACE" at ERROR;
break;
now entry x in entry y in D20P1 grid is step;
To decide which number is the D20P1 result:
let count be 0;
repeat with y running from 2 to D20P1 grid height - 1:
repeat with x running from 2 to D20P1 grid width - 1:
[Only look at walls.]
if entry x in entry y in D20P1 grid is not -1, next;
[Vertically:]
let up be entry x in entry y - 1 in D20P1 grid;
let down be entry x in entry y + 1 in D20P1 grid;
if up is not -1 and down is not -1:
let saved be (the integer absolute value of (up - down)) - 2;
if saved >= 100:
increment count;
let left be entry x - 1 in entry y in D20P1 grid;
let right be entry x + 1 in entry y in D20P1 grid;
if left is not -1 and right is not -1:
let saved be (the integer absolute value of (left - right)) - 2;
if saved >= 100:
increment count;
decide on count;
To complete the D20P1 computation:
trace the D20P1 race track;
say "[D20P1 result]";
now D20P2 grid is {};
disable raw input;
unpush D20P1 button;
Section - Part 2
D20P2 button is a part 2 button.
D20P2 button is here.
D20P2 scene is a recurring scene.
D20P2 scene begins when D20P2 button is switched on.
D20P2 scene ends when D20P2 button is switched off.
Table of Stars (continued)
Day Part Button
20 2 D20P2 button
D20P2 grid is a list of list of numbers that varies.
D20P2 grid width is a number that varies.
D20P2 grid height is a number that varies.
D20P2 start x is a number that varies.
D20P2 start y is a number that varies.
D20P2 end x is a number that varies.
D20P2 end y is a number that varies.
D20P2 path x is a list of numbers that varies.
D20P2 path y is a list of numbers that varies.
When D20P2 scene begins:
enable raw input;
now D20P2 grid is {};
now D20P2 grid width is 0;
now D20P2 grid height is 0;
now D20P2 path x is {};
now D20P2 path y is {};
To add (line - text) to the D20P2 grid:
let n be the number of characters in line;
if D20P2 grid width is 0:
now D20P2 grid width is n;
increment D20P2 grid height;
let row be a list of numbers;
repeat with x running from 1 to n:
let c be character number x in line;
if c is "#":
add -1 to row;
else if c is ".":
add 0 to row;
else if c is "S":
add 0 to row;
now D20P2 start x is x;
now D20P2 start y is D20P2 grid height;
else if c is "E":
add 0 to row;
now D20P2 end x is x;
now D20P2 end y is D20P2 grid height;
else:
log "BAD GRID CHARACTER: [c]" at ERROR;
add row to D20P2 grid;
After reading a raw input when D20P2 scene is happening:
let line be the raw input;
if line is "":
complete the D20P2 computation;
else:
add line to the D20P2 grid;
To trace the D20P2 race track:
let x be D20P2 start x;
let y be D20P2 start y;
let step be 1;
while x is not D20P2 end x or y is not D20P2 end y:
now entry x in entry y in D20P2 grid is step;
increment step;
if x > 1 and entry x - 1 in entry y in D20P2 grid is 0:
decrement x;
else if x < D20P2 grid width and entry x + 1 in entry y in D20P2 grid is 0:
increment x;
else if y > 1 and entry x in entry y - 1 in D20P2 grid is 0:
decrement y;
else if y < D20P2 grid height and entry x in entry y + 1 in D20P2 grid is 0:
increment y;
else:
log "FAILED TO TRACE" at ERROR;
break;
now entry x in entry y in D20P2 grid is step;
D20P2 minimum save is always 100.
To decide which number is the D20P2 result:
let count be 0;
repeat with ay running from 1 to D20P2 grid height:
log "ay = [ay]" at INFO every 10 of ay;
repeat with ax running from 1 to D20P2 grid width:
[Only look at spaces.]
let a be entry ax in entry ay in D20P2 grid;
if a is -1, next;
repeat with by running from ay - 20 to ay + 20:
if by < 1 or by > D20P2 grid height, next;
let dy be the integer absolute value of (by - ay);
repeat with bx running from ax - 20 to ax + 20:
if bx < 1 or bx > D20P2 grid width, next;
let b be entry bx in entry by in D20P2 grid;
if b is -1, next;
if b < a, next;
let dx be the integer absolute value of (bx - ax);
let distance be dx + dy;
if distance > 20, next;
let saved be (b - a) - distance;
if saved >= D20P2 minimum save:
increment count;
decide on count;
[
To trace the D20P2 race track:
let x be D20P2 start x;
let y be D20P2 start y;
let step be 1;
while x is not D20P2 end x or y is not D20P2 end y:
add x to D20P2 path x;
add y to D20P2 path y;
now entry x in entry y in D20P2 grid is step;
increment step;
if x > 1 and entry x - 1 in entry y in D20P2 grid is 0:
decrement x;
else if x < D20P2 grid width and entry x + 1 in entry y in D20P2 grid is 0:
increment x;
else if y > 1 and entry x in entry y - 1 in D20P2 grid is 0:
decrement y;
else if y < D20P2 grid height and entry x in entry y + 1 in D20P2 grid is 0:
increment y;
else:
log "FAILED TO TRACE" at ERROR;
break;
add x to D20P2 path x;
add y to D20P2 path y;
now entry x in entry y in D20P2 grid is step;
D20P2 minimum save is always 100.
To decide which number is the D20P2 result:
let n be the number of entries in D20P2 path x;
let count be 0;
repeat with i running from D20P2 minimum save + 1 to n:
log "i = [i]" at INFO every 10 of i;
let ax be entry i in D20P2 path x;
let ay be entry i in D20P2 path y;
repeat with j running from 1 to i - D20P2 minimum save:
let bx be entry j in D20P2 path x;
let by be entry j in D20P2 path y;
let distance be the manhattan distance from ax and ay to bx and by;
if distance <= 20:
let s be (i - j) - distance;
if s >= D20P2 minimum save:
increment count;
decide on count;
]
To complete the D20P2 computation:
trace the D20P2 race track;
say "[D20P2 result]";
now D20P2 grid is {};
now D20P2 path x is {};
now D20P2 path y is {};
disable raw input;
unpush D20P2 button;
Chapter - Day 21
Day 21 is a room.
d21 is a direction. d21 has opposite outside. Index map with d21 mapped as inside.
Door 21 is a door. Door 21 is d21 of the Vortex and outside of Day 21.
Section - Part 1
D21P1 button is a part 1 button.
D21P1 button is here.
D21P1 scene is a recurring scene.
D21P1 scene begins when D21P1 button is switched on.
D21P1 scene ends when D21P1 button is switched off.
Table of Stars (continued)
Day Part Button
21 1 D21P1 button
D21P1 result is a number that varies.
When D21P1 scene begins:
now D21P1 result is 0;
Entering a D21P1 line is an action applying to one topic.
Understand "[text]" as entering a D21P1 line while D21P1 scene is happening.
D21_INVALID is always -1.
D21_NUMERIC_0 is always 0.
D21_NUMERIC_1 is always 1.
D21_NUMERIC_2 is always 2.
D21_NUMERIC_3 is always 3.
D21_NUMERIC_4 is always 4.
D21_NUMERIC_5 is always 5.
D21_NUMERIC_6 is always 6.
D21_NUMERIC_7 is always 7.
D21_NUMERIC_8 is always 8.
D21_NUMERIC_9 is always 9.
D21_A is always 10.
D21_DIRECTIONAL_L is always 11.
D21_DIRECTIONAL_R is always 12.
D21_DIRECTIONAL_U is always 13.
D21_DIRECTIONAL_D is always 14.
To decide which number is the D21P1 numeric transition of (state - number) with (direction - number):
if state is D21_NUMERIC_7:
if direction is D21_DIRECTIONAL_R, decide on D21_NUMERIC_8;
if direction is D21_DIRECTIONAL_D, decide on D21_NUMERIC_4;
if state is D21_NUMERIC_8:
if direction is D21_DIRECTIONAL_L, decide on D21_NUMERIC_7;
if direction is D21_DIRECTIONAL_R, decide on D21_NUMERIC_9;
if direction is D21_DIRECTIONAL_D, decide on D21_NUMERIC_5;
if state is D21_NUMERIC_9:
if direction is D21_DIRECTIONAL_L, decide on D21_NUMERIC_8;
if direction is D21_DIRECTIONAL_D, decide on D21_NUMERIC_6;
if state is D21_NUMERIC_4:
if direction is D21_DIRECTIONAL_R, decide on D21_NUMERIC_5;
if direction is D21_DIRECTIONAL_U, decide on D21_NUMERIC_7;
if direction is D21_DIRECTIONAL_D, decide on D21_NUMERIC_1;
if state is D21_NUMERIC_5:
if direction is D21_DIRECTIONAL_L, decide on D21_NUMERIC_4;
if direction is D21_DIRECTIONAL_R, decide on D21_NUMERIC_6;
if direction is D21_DIRECTIONAL_U, decide on D21_NUMERIC_8;
if direction is D21_DIRECTIONAL_D, decide on D21_NUMERIC_2;
if state is D21_NUMERIC_6:
if direction is D21_DIRECTIONAL_L, decide on D21_NUMERIC_5;
if direction is D21_DIRECTIONAL_U, decide on D21_NUMERIC_9;
if direction is D21_DIRECTIONAL_D, decide on D21_NUMERIC_3;
if state is D21_NUMERIC_1:
if direction is D21_DIRECTIONAL_R, decide on D21_NUMERIC_2;
if direction is D21_DIRECTIONAL_U, decide on D21_NUMERIC_4;
if state is D21_NUMERIC_2:
if direction is D21_DIRECTIONAL_L, decide on D21_NUMERIC_1;
if direction is D21_DIRECTIONAL_R, decide on D21_NUMERIC_3;
if direction is D21_DIRECTIONAL_U, decide on D21_NUMERIC_5;
if direction is D21_DIRECTIONAL_D, decide on D21_NUMERIC_0;
if state is D21_NUMERIC_3:
if direction is D21_DIRECTIONAL_L, decide on D21_NUMERIC_1;
if direction is D21_DIRECTIONAL_U, decide on D21_NUMERIC_6;
if direction is D21_DIRECTIONAL_D, decide on D21_A;
if state is D21_NUMERIC_0:
if direction is D21_DIRECTIONAL_R, decide on D21_A;
if direction is D21_DIRECTIONAL_U, decide on D21_NUMERIC_2;
if state is D21_A:
if direction is D21_DIRECTIONAL_L, decide on D21_NUMERIC_0;
if direction is D21_DIRECTIONAL_U, decide on D21_NUMERIC_3;
decide on D21_INVALID;
To decide which number is the D21P1 directional transition of (state - number) with (direction - number):
if state is D21_DIRECTIONAL_U:
if direction is D21_DIRECTIONAL_R, decide on D21_A;
if direction is D21_DIRECTIONAL_D, decide on D21_DIRECTIONAL_D;
if state is D21_A:
if direction is D21_DIRECTIONAL_L, decide on D21_DIRECTIONAL_U;
if direction is D21_DIRECTIONAL_D, decide on D21_DIRECTIONAL_R;
if state is D21_DIRECTIONAL_L:
if direction is D21_DIRECTIONAL_R, decide on D21_DIRECTIONAL_D;
if state is D21_DIRECTIONAL_D:
if direction is D21_DIRECTIONAL_L, decide on D21_DIRECTIONAL_L;
if direction is D21_DIRECTIONAL_R, decide on D21_DIRECTIONAL_R;
if direction is D21_DIRECTIONAL_U, decide on D21_DIRECTIONAL_U;
if state is D21_DIRECTIONAL_R:
if direction is D21_DIRECTIONAL_L, decide on D21_DIRECTIONAL_D;
if direction is D21_DIRECTIONAL_U, decide on D21_A;
decide on D21_INVALID;
[(sequence length, output length, directional keypad 1 state,
directional keypad 2 state, ..., directional keypad N state,
numeric keypad state), ...]
D21P1 todo is a list of list of numbers that varies.
To pop the first entry of D21P1 todo:
[Replace the first entry with the last entry]
let n be the number of entries in D21P1 todo;
let v be entry n in D21P1 todo;
now entry 1 in D21P1 todo is v;
remove entry n in D21P1 todo;
decrement n;
[Move nodes down as needed]
let i be 1;
while true is true:
let smallest index be i;
let left index be binary heap left child of i;
let right index be binary heap right child of i;
if left index <= n and entry left index in D21P1 todo < entry smallest index in D21P1 todo:
now smallest index is left index;
if right index <= n and entry right index in D21P1 todo < entry smallest index in D21P1 todo:
now smallest index is right index;
if smallest index is not i:
swap entry i and smallest index in D21P1 todo;
now i is smallest index;
else:
break;
To insert (entry - list of numbers) into D21P1 todo:
add entry to D21P1 todo;
let i be the number of entries in D21P1 todo;
while i > 1:
let j be the binary heap parent of i;
let parent be entry j in D21P1 todo;
if parent <= entry, break;
now entry i in D21P1 todo is parent;
now i is j;
now entry i in D21P1 todo is entry;
To decide which number is the D21P1 shortest sequence of (target - text):
now target is target in upper case;
now D21P1 todo is {};
let initial entry be a list of numbers;
add 0 to initial entry; [sequence length]
add 0 to initial entry; [output length]
add D21_A to initial entry; [directional]
add D21_A to initial entry; [directional]
add D21_A to initial entry; [numeric]
add initial entry to D21P1 todo;
let target length be the number of characters in target;
let sorted done be a list of list of numbers;
let unsorted done be a list of list of numbers;
while D21P1 todo is not empty:
let current entry be entry 1 of D21P1 todo;
let current sequence length be entry 1 in current entry;
if entry 2 in current entry is target length:
now D21P1 todo is {};
decide on current sequence length;
pop the first entry of D21P1 todo;
remove entry 1 in current entry;
if current entry is in already-sorted sorted done:
next;
if current entry is listed in unsorted done:
next;
add current entry to unsorted done;
if the number of entries in unsorted done > 100:
sort unsorted done;
now sorted done is the merge of already-sorted sorted done and unsorted done;
now unsorted done is {};
increment current sequence length;
[These moves can only affect the first numeric keypad]
repeat with m running through {D21_DIRECTIONAL_U, D21_DIRECTIONAL_D, D21_DIRECTIONAL_L, D21_DIRECTIONAL_R}:
let first keypad state be entry 2 in current entry;
now first keypad state is the D21P1 directional transition of first keypad state with m;
if first keypad state is not D21_INVALID:
let new entry be a list of numbers;
add current sequence length to new entry;
add entry 1 in current entry to new entry;
add first keypad state to new entry;
add entry 3 in current entry to new entry;
add entry 4 in current entry to new entry;
insert new entry into D21P1 todo;
[Press A: we need to find the first keypad that doesn't point at A]
let n be the number of entries in current entry;
let i be 2;
while i < n and entry i in current entry is D21_A:
increment i;
if i is n:
[We've pressed a button on the numeric keypad]
let current output index be (entry 1 in current entry) + 1;
let expected output be character number current output index in target;
if ("[entry n in current entry]" exactly matches the text expected output) or (entry n in current entry is D21_A and expected output is "A"):
[We pressed the button we wanted to find]
let new entry be a list of numbers;
add current sequence length to new entry;
add current output index to new entry;
add entry 2 in current entry to new entry;
add entry 3 in current entry to new entry;
add entry 4 in current entry to new entry;
insert new entry into D21P1 todo;
else:
[Apply the previous keypad's directional move to this keypad]
let m be entry i in current entry;
let keypad state be entry i + 1 in current entry;
if i is n - 1:
now keypad state is the D21P1 numeric transition of keypad state with m;
else:
now keypad state is the D21P1 directional transition of keypad state with m;
if keypad state is not D21_INVALID:
let new entry be a list of numbers;
add current sequence length to new entry;
add entry 1 in current entry to new entry;
repeat with j running from 2 to i:
add entry j in current entry to new entry;
add keypad state to new entry;
repeat with j running from i + 2 to n:
add entry j in current entry to new entry;
insert new entry into D21P1 todo;
decide on -1;
Carry out entering a D21P1 line:
let target be the topic understood;
let x be the D21P1 shortest sequence of target;
let y be (the substring of target from 1 to (number of characters in target - 1)) understood as a number;
let xy be x * y;
log "[x] * [y] = [xy]" at INFO;
increase D21P1 result by xy;
Before entering a blank line while D21P1 scene is happening:
say "[D21P1 result]";
unpush D21P1 button;
Section - Part 2
D21P2 button is a part 2 button.
D21P2 button is here.
D21P2 scene is a recurring scene.
D21P2 scene begins when D21P2 button is switched on.
D21P2 scene ends when D21P2 button is switched off.
Table of Stars (continued)
Day Part Button
21 2 D21P2 button
D21P2 cache is a list of list of list of numbers that varies.
D21P2 result is a list of number that varies.
D21P2_NUMERIC_LEVELS is always 26.
When D21P2 scene begins:
now D21P2 result is BIGNUM_ZERO;
now D21P2 cache is {};
repeat with i running from 1 to D21P2_NUMERIC_LEVELS:
let row be a list of list of numbers;
repeat with j running from 1 to D21P2_NUM_NUMERIC_PATHS:
let x be a list of numbers;
add x to row;
add row to D21P2 cache;
Entering a D21P2 line is an action applying to one topic.
Understand "[text]" as entering a D21P2 line while D21P2 scene is happening.
D21P2_PATH_A is always 1.
D21P2_PATH_DA is always 2.
D21P2_PATH_LA is always 3.
D21P2_PATH_LDA is always 4.
D21P2_PATH_DLA is always 5.
D21P2_PATH_DLLA is always 6.
D21P2_PATH_RA is always 7.
D21P2_PATH_RDA is always 8.
D21P2_PATH_DRA is always 9.
D21P2_PATH_RRUA is always 10.
D21P2_PATH_RUA is always 11.
D21P2_PATH_RRA is always 12.
D21P2_PATH_URA is always 13.
D21P2_PATH_UA is always 14.
D21P2_PATH_ULA is always 15.
D21P2_PATH_LUA is always 16.
D21P2_PATH_LLA is always 17.
D21P2_NUM_NUMERIC_PATHS is always 17.
D21P2_PATH_ULLA is always 18.
D21P2_PATH_UULLA is always 19.
D21P2_PATH_LUUA is always 20.
D21P2_PATH_UULA is always 21.
D21P2_PATH_UUA is always 22.
D21P2_PATH_UUULLA is always 23.
D21P2_PATH_LUUUA is always 24.
D21P2_PATH_UUULA is always 25.
D21P2_PATH_UUUA is always 26.
D21P2_PATH_UURA is always 27.
D21P2_PATH_RUUA is always 28.
D21P2_PATH_UUURA is always 29.
D21P2_PATH_RUUUA is always 30.
D21P2_PATH_RRDA is always 31.
D21P2_PATH_RRUUA is always 32.
D21P2_PATH_UURRA is always 33.
D21P2_PATH_LLUA is always 34.
D21P2_PATH_LLUUA is always 35.
D21P2_PATH_RRDDA is always 36.
D21P2_PATH_RDDA is always 37.
D21P2_PATH_DRRA is always 38.
D21P2_PATH_DDRA is always 39.
D21P2_PATH_DDA is always 40.
D21P2_PATH_LDDA is always 41.
D21P2_PATH_URRA is always 42.
D21P2_PATH_DDLA is always 43.
D21P2_PATH_LLDA is always 44.
D21P2_PATH_RRDDDA is always 45.
D21P2_PATH_RDDDA is always 46.
D21P2_PATH_DDRRA is always 47.
D21P2_PATH_DDDRA is always 48.
D21P2_PATH_DDDA is always 49.
D21P2_PATH_LDDDA is always 50.
D21P2_PATH_DDDLA is always 51.
D21P2_PATH_LLDDA is always 52.
D21P2_PATH_DDLLA is always 53.
D21P2_NUM_PATHS is always 53.
To decide which list of number is the D21P2 buttons of (path - number):
if path is D21P2_PATH_A, decide on {D21_A};
if path is D21P2_PATH_DA, decide on {D21_DIRECTIONAL_D, D21_A};
if path is D21P2_PATH_LA, decide on {D21_DIRECTIONAL_L, D21_A};
if path is D21P2_PATH_LDA, decide on {D21_DIRECTIONAL_L, D21_DIRECTIONAL_D, D21_A};
if path is D21P2_PATH_DLA, decide on {D21_DIRECTIONAL_D, D21_DIRECTIONAL_L, D21_A};
if path is D21P2_PATH_DLLA, decide on {D21_DIRECTIONAL_D, D21_DIRECTIONAL_L, D21_DIRECTIONAL_L, D21_A};
if path is D21P2_PATH_RA, decide on {D21_DIRECTIONAL_R, D21_A};
if path is D21P2_PATH_RDA, decide on {D21_DIRECTIONAL_R, D21_DIRECTIONAL_D, D21_A};
if path is D21P2_PATH_DRA, decide on {D21_DIRECTIONAL_D, D21_DIRECTIONAL_R, D21_A};
if path is D21P2_PATH_RRUA, decide on {D21_DIRECTIONAL_R, D21_DIRECTIONAL_R, D21_DIRECTIONAL_U, D21_A};
if path is D21P2_PATH_RUA, decide on {D21_DIRECTIONAL_R, D21_DIRECTIONAL_U, D21_A};
if path is D21P2_PATH_RRA, decide on {D21_DIRECTIONAL_R, D21_DIRECTIONAL_R, D21_A};
if path is D21P2_PATH_URA, decide on {D21_DIRECTIONAL_U, D21_DIRECTIONAL_R, D21_A};
if path is D21P2_PATH_UA, decide on {D21_DIRECTIONAL_U, D21_A};
if path is D21P2_PATH_ULA, decide on {D21_DIRECTIONAL_U, D21_DIRECTIONAL_L, D21_A};
if path is D21P2_PATH_LUA, decide on {D21_DIRECTIONAL_L, D21_DIRECTIONAL_U, D21_A};
if path is D21P2_PATH_LLA, decide on {D21_DIRECTIONAL_L, D21_DIRECTIONAL_L, D21_A};
if path is D21P2_PATH_ULLA, decide on {D21_DIRECTIONAL_U, D21_DIRECTIONAL_L, D21_DIRECTIONAL_L, D21_A};
if path is D21P2_PATH_UULLA, decide on {D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_DIRECTIONAL_L, D21_DIRECTIONAL_L, D21_A};
if path is D21P2_PATH_LUUA, decide on {D21_DIRECTIONAL_L, D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_A};
if path is D21P2_PATH_UULA, decide on {D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_DIRECTIONAL_L, D21_A};
if path is D21P2_PATH_UUA, decide on {D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_A};
if path is D21P2_PATH_UUULLA, decide on {D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_DIRECTIONAL_L, D21_DIRECTIONAL_L, D21_A};
if path is D21P2_PATH_LUUUA, decide on {D21_DIRECTIONAL_L, D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_A};
if path is D21P2_PATH_UUULA, decide on {D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_DIRECTIONAL_L, D21_A};
if path is D21P2_PATH_UUUA, decide on {D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_A};
if path is D21P2_PATH_UURA, decide on {D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_DIRECTIONAL_R, D21_A};
if path is D21P2_PATH_RUUA, decide on {D21_DIRECTIONAL_R, D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_A};
if path is D21P2_PATH_UUURA, decide on {D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_DIRECTIONAL_R, D21_A};
if path is D21P2_PATH_RUUUA, decide on {D21_DIRECTIONAL_R, D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_A};
if path is D21P2_PATH_RRDA, decide on {D21_DIRECTIONAL_R, D21_DIRECTIONAL_R, D21_DIRECTIONAL_D, D21_A};
if path is D21P2_PATH_RRUUA, decide on {D21_DIRECTIONAL_R, D21_DIRECTIONAL_R, D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_A};
if path is D21P2_PATH_UURRA, decide on {D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_DIRECTIONAL_R, D21_DIRECTIONAL_R, D21_A};
if path is D21P2_PATH_LLUA, decide on {D21_DIRECTIONAL_L, D21_DIRECTIONAL_L, D21_DIRECTIONAL_U, D21_A};
if path is D21P2_PATH_LLUUA, decide on {D21_DIRECTIONAL_L, D21_DIRECTIONAL_L, D21_DIRECTIONAL_U, D21_DIRECTIONAL_U, D21_A};
if path is D21P2_PATH_RRDDA, decide on {D21_DIRECTIONAL_R, D21_DIRECTIONAL_R, D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_A};
if path is D21P2_PATH_RDDA, decide on {D21_DIRECTIONAL_R, D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_A};
if path is D21P2_PATH_DRRA, decide on {D21_DIRECTIONAL_D, D21_DIRECTIONAL_R, D21_DIRECTIONAL_R, D21_A};
if path is D21P2_PATH_DDRA, decide on {D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_DIRECTIONAL_R, D21_A};
if path is D21P2_PATH_DDA, decide on {D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_A};
if path is D21P2_PATH_LDDA, decide on {D21_DIRECTIONAL_L, D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_A};
if path is D21P2_PATH_URRA, decide on {D21_DIRECTIONAL_U, D21_DIRECTIONAL_R, D21_DIRECTIONAL_R, D21_A};
if path is D21P2_PATH_DDLA, decide on {D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_DIRECTIONAL_L, D21_A};
if path is D21P2_PATH_LLDA, decide on {D21_DIRECTIONAL_L, D21_DIRECTIONAL_L, D21_DIRECTIONAL_D, D21_A};
if path is D21P2_PATH_RRDDDA, decide on {D21_DIRECTIONAL_R, D21_DIRECTIONAL_R, D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_A};
if path is D21P2_PATH_RDDDA, decide on {D21_DIRECTIONAL_R, D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_A};
if path is D21P2_PATH_DDRRA, decide on {D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_DIRECTIONAL_R, D21_DIRECTIONAL_R, D21_A};
if path is D21P2_PATH_DDDRA, decide on {D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_DIRECTIONAL_R, D21_A};
if path is D21P2_PATH_DDDA, decide on {D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_A};
if path is D21P2_PATH_LDDDA, decide on {D21_DIRECTIONAL_L, D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_A};
if path is D21P2_PATH_DDDLA, decide on {D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_DIRECTIONAL_L, D21_A};
if path is D21P2_PATH_LLDDA, decide on {D21_DIRECTIONAL_L, D21_DIRECTIONAL_L, D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_A};
if path is D21P2_PATH_DDLLA, decide on {D21_DIRECTIONAL_D, D21_DIRECTIONAL_D, D21_DIRECTIONAL_L, D21_DIRECTIONAL_L, D21_A};
log "UNKNOWN PATH [path]" at ERROR;
decide on {};
To decide which list of number is the D21P2 possible paths from (x - number) to (y - number):
if x is y:
decide on {D21P2_PATH_A};
if x is D21_A:
if y is D21_DIRECTIONAL_R, decide on {D21P2_PATH_DA};
if y is D21_DIRECTIONAL_U, decide on {D21P2_PATH_LA};
if y is D21_DIRECTIONAL_D, decide on {D21P2_PATH_LDA, D21P2_PATH_DLA};
if y is D21_DIRECTIONAL_L, decide on {D21P2_PATH_DLLA};
if y is D21_NUMERIC_0, decide on {D21P2_PATH_LA};
if y is D21_NUMERIC_1, decide on {D21P2_PATH_ULLA};
if y is D21_NUMERIC_2, decide on {D21P2_PATH_ULA, D21P2_PATH_LUA};
if y is D21_NUMERIC_3, decide on {D21P2_PATH_UA};
if y is D21_NUMERIC_4, decide on {D21P2_PATH_UULLA};
if y is D21_NUMERIC_5, decide on {D21P2_PATH_LUUA, D21P2_PATH_UULA};
if y is D21_NUMERIC_6, decide on {D21P2_PATH_UUA};
if y is D21_NUMERIC_7, decide on {D21P2_PATH_UUULLA};
if y is D21_NUMERIC_8, decide on {D21P2_PATH_LUUUA, D21P2_PATH_UUULA};
if y is D21_NUMERIC_9, decide on {D21P2_PATH_UUUA};
if x is D21_DIRECTIONAL_U:
if y is D21_A, decide on {D21P2_PATH_RA};
if y is D21_DIRECTIONAL_R, decide on {D21P2_PATH_RDA, D21P2_PATH_DRA};
if y is D21_DIRECTIONAL_D, decide on {D21P2_PATH_DA};
if y is D21_DIRECTIONAL_L, decide on {D21P2_PATH_DLA};
if x is D21_DIRECTIONAL_L:
if y is D21_A, decide on {D21P2_PATH_RRUA};
if y is D21_DIRECTIONAL_U, decide on {D21P2_PATH_RUA};
if y is D21_DIRECTIONAL_D, decide on {D21P2_PATH_RA};
if y is D21_DIRECTIONAL_R, decide on {D21P2_PATH_RRA};
if x is D21_DIRECTIONAL_D:
if y is D21_A, decide on {D21P2_PATH_URA, D21P2_PATH_RUA};
if y is D21_DIRECTIONAL_U, decide on {D21P2_PATH_UA};
if y is D21_DIRECTIONAL_L, decide on {D21P2_PATH_LA};
if y is D21_DIRECTIONAL_R, decide on {D21P2_PATH_RA};
if x is D21_DIRECTIONAL_R:
if y is D21_A, decide on {D21P2_PATH_UA};
if y is D21_DIRECTIONAL_U, decide on {D21P2_PATH_ULA, D21P2_PATH_LUA};
if y is D21_DIRECTIONAL_D, decide on {D21P2_PATH_LA};
if y is D21_DIRECTIONAL_L, decide on {D21P2_PATH_LLA};
if x is D21_NUMERIC_0:
if y is D21_A, decide on {D21P2_PATH_RA};
if y is D21_NUMERIC_1, decide on {D21P2_PATH_ULA};
if y is D21_NUMERIC_2, decide on {D21P2_PATH_UA};
if y is D21_NUMERIC_3, decide on {D21P2_PATH_RUA, D21P2_PATH_URA};
if y is D21_NUMERIC_4, decide on {D21P2_PATH_UULA};
if y is D21_NUMERIC_5, decide on {D21P2_PATH_UUA};
if y is D21_NUMERIC_6, decide on {D21P2_PATH_UURA, D21P2_PATH_RUUA};
if y is D21_NUMERIC_7, decide on {D21P2_PATH_UUULA};
if y is D21_NUMERIC_8, decide on {D21P2_PATH_UUUA};
if y is D21_NUMERIC_9, decide on {D21P2_PATH_UUURA, D21P2_PATH_RUUUA};
if x is D21_NUMERIC_1:
if y is D21_A, decide on {D21P2_PATH_RRDA};
if y is D21_NUMERIC_0, decide on {D21P2_PATH_RDA};
if y is D21_NUMERIC_2, decide on {D21P2_PATH_RA};
if y is D21_NUMERIC_3, decide on {D21P2_PATH_RRA};
if y is D21_NUMERIC_4, decide on {D21P2_PATH_UA};
if y is D21_NUMERIC_5, decide on {D21P2_PATH_URA, D21P2_PATH_RUA};
if y is D21_NUMERIC_6, decide on {D21P2_PATH_RRUA, D21P2_PATH_URRA};
if y is D21_NUMERIC_7, decide on {D21P2_PATH_UUA};
if y is D21_NUMERIC_8, decide on {D21P2_PATH_UURA, D21P2_PATH_RUUA};
if y is D21_NUMERIC_9, decide on {D21P2_PATH_RRUUA, D21P2_PATH_UURRA};
if x is D21_NUMERIC_2:
if y is D21_A, decide on {D21P2_PATH_RDA, D21P2_PATH_DRA};
if y is D21_NUMERIC_0, decide on {D21P2_PATH_DA};
if y is D21_NUMERIC_1, decide on {D21P2_PATH_LA};
if y is D21_NUMERIC_3, decide on {D21P2_PATH_RA};
if y is D21_NUMERIC_4, decide on {D21P2_PATH_LUA, D21P2_PATH_ULA};
if y is D21_NUMERIC_5, decide on {D21P2_PATH_UA};
if y is D21_NUMERIC_6, decide on {D21P2_PATH_RUA, D21P2_PATH_URA};
if y is D21_NUMERIC_7, decide on {D21P2_PATH_LUUA, D21P2_PATH_UULA};
if y is D21_NUMERIC_8, decide on {D21P2_PATH_UUA};
if y is D21_NUMERIC_9, decide on {D21P2_PATH_UURA};
if x is D21_NUMERIC_3:
if y is D21_A, decide on {D21P2_PATH_DA};
if y is D21_NUMERIC_0, decide on {D21P2_PATH_LDA, D21P2_PATH_DLA};
if y is D21_NUMERIC_1, decide on {D21P2_PATH_LLA};
if y is D21_NUMERIC_2, decide on {D21P2_PATH_LA};
if y is D21_NUMERIC_4, decide on {D21P2_PATH_LLUA, D21P2_PATH_ULLA};
if y is D21_NUMERIC_5, decide on {D21P2_PATH_ULA, D21P2_PATH_LUA};
if y is D21_NUMERIC_6, decide on {D21P2_PATH_UA};
if y is D21_NUMERIC_7, decide on {D21P2_PATH_LLUUA, D21P2_PATH_UULLA};
if y is D21_NUMERIC_8, decide on {D21P2_PATH_LUUA, D21P2_PATH_UULA};
if y is D21_NUMERIC_9, decide on {D21P2_PATH_UUA};
if x is D21_NUMERIC_4:
if y is D21_A, decide on {D21P2_PATH_RRDDA};
if y is D21_NUMERIC_0, decide on {D21P2_PATH_RDDA};
if y is D21_NUMERIC_1, decide on {D21P2_PATH_DA};
if y is D21_NUMERIC_2, decide on {D21P2_PATH_RDA, D21P2_PATH_DRA};
if y is D21_NUMERIC_3, decide on {D21P2_PATH_RRDA, D21P2_PATH_DRRA};
if y is D21_NUMERIC_5, decide on {D21P2_PATH_RA};
if y is D21_NUMERIC_6, decide on {D21P2_PATH_RRA};
if y is D21_NUMERIC_7, decide on {D21P2_PATH_UA};
if y is D21_NUMERIC_8, decide on {D21P2_PATH_RUA, D21P2_PATH_URA};
if y is D21_NUMERIC_9, decide on {D21P2_PATH_RRUA, D21P2_PATH_URRA};
if x is D21_NUMERIC_5:
if y is D21_A, decide on {D21P2_PATH_RDDA, D21P2_PATH_DDRA};
if y is D21_NUMERIC_0, decide on {D21P2_PATH_DDA};
if y is D21_NUMERIC_1, decide on {D21P2_PATH_DLA, D21P2_PATH_LDA};
if y is D21_NUMERIC_2, decide on {D21P2_PATH_DA};
if y is D21_NUMERIC_3, decide on {D21P2_PATH_DRA, D21P2_PATH_RDA};
if y is D21_NUMERIC_4, decide on {D21P2_PATH_LA};
if y is D21_NUMERIC_6, decide on {D21P2_PATH_RA};
if y is D21_NUMERIC_7, decide on {D21P2_PATH_LUA, D21P2_PATH_ULA};
if y is D21_NUMERIC_8, decide on {D21P2_PATH_UA};
if y is D21_NUMERIC_9, decide on {D21P2_PATH_URA, D21P2_PATH_RUA};
if x is D21_NUMERIC_6:
if y is D21_A, decide on {D21P2_PATH_DDA};
if y is D21_NUMERIC_0, decide on {D21P2_PATH_LDDA, D21P2_PATH_DDLA};
if y is D21_NUMERIC_1, decide on {D21P2_PATH_LLDA, D21P2_PATH_DLLA};
if y is D21_NUMERIC_2, decide on {D21P2_PATH_DLA, D21P2_PATH_LDA};
if y is D21_NUMERIC_3, decide on {D21P2_PATH_DA};
if y is D21_NUMERIC_4, decide on {D21P2_PATH_LLA};
if y is D21_NUMERIC_5, decide on {D21P2_PATH_LA};
if y is D21_NUMERIC_7, decide on {D21P2_PATH_LLUA, D21P2_PATH_ULLA};
if y is D21_NUMERIC_8, decide on {D21P2_PATH_LUA, D21P2_PATH_ULA};
if y is D21_NUMERIC_9, decide on {D21P2_PATH_UA};
if x is D21_NUMERIC_7:
if y is D21_A, decide on {D21P2_PATH_RRDDDA};
if y is D21_NUMERIC_0, decide on {D21P2_PATH_RDDDA};
if y is D21_NUMERIC_1, decide on {D21P2_PATH_DDA};
if y is D21_NUMERIC_2, decide on {D21P2_PATH_RDDA, D21P2_PATH_DDRA};
if y is D21_NUMERIC_3, decide on {D21P2_PATH_DDRRA, D21P2_PATH_RRDDA};
if y is D21_NUMERIC_4, decide on {D21P2_PATH_DA};
if y is D21_NUMERIC_5, decide on {D21P2_PATH_DRA, D21P2_PATH_RDA};
if y is D21_NUMERIC_6, decide on {D21P2_PATH_RRDA, D21P2_PATH_DRRA};
if y is D21_NUMERIC_8, decide on {D21P2_PATH_RA};
if y is D21_NUMERIC_9, decide on {D21P2_PATH_RRA};
if x is D21_NUMERIC_8:
if y is D21_A, decide on {D21P2_PATH_RDDDA, D21P2_PATH_DDDRA};
if y is D21_NUMERIC_0, decide on {D21P2_PATH_DDDA};
if y is D21_NUMERIC_1, decide on {D21P2_PATH_LDDA, D21P2_PATH_DDLA};
if y is D21_NUMERIC_2, decide on {D21P2_PATH_DDA};
if y is D21_NUMERIC_3, decide on {D21P2_PATH_DDRA, D21P2_PATH_RDDA};
if y is D21_NUMERIC_4, decide on {D21P2_PATH_DLA, D21P2_PATH_LDA};
if y is D21_NUMERIC_5, decide on {D21P2_PATH_DA};
if y is D21_NUMERIC_6, decide on {D21P2_PATH_DRA, D21P2_PATH_RDA};
if y is D21_NUMERIC_7, decide on {D21P2_PATH_LA};
if y is D21_NUMERIC_9, decide on {D21P2_PATH_RA};
if x is D21_NUMERIC_9:
if y is D21_A, decide on {D21P2_PATH_DDDA};
if y is D21_NUMERIC_0, decide on {D21P2_PATH_LDDDA, D21P2_PATH_DDDLA};
if y is D21_NUMERIC_1, decide on {D21P2_PATH_LLDDA, D21P2_PATH_DDLLA};
if y is D21_NUMERIC_2, decide on {D21P2_PATH_LDDA, D21P2_PATH_DDLA};
if y is D21_NUMERIC_3, decide on {D21P2_PATH_DDA};
if y is D21_NUMERIC_4, decide on {D21P2_PATH_LLDA, D21P2_PATH_DLLA};
if y is D21_NUMERIC_5, decide on {D21P2_PATH_DLA, D21P2_PATH_LDA};
if y is D21_NUMERIC_6, decide on {D21P2_PATH_DA};
if y is D21_NUMERIC_7, decide on {D21P2_PATH_LLA};
if y is D21_NUMERIC_8, decide on {D21P2_PATH_LA};
To decide what list of number is the D21P2 shortest sequence length for (path - number) at (level - number):
if path <= D21P2_NUM_NUMERIC_PATHS:
let cached be entry path in entry level in D21P2 cache;
if cached is not empty, decide on cached;
if level is 1:
let s be (the number of entries in the D21P2 buttons of path) converted to bignum;
now entry path in entry 1 in D21P2 cache is s;
decide on s;
let steps be BIGNUM_ZERO;
let button be D21_A;
repeat with target running through the D21P2 buttons of path:
let best be a list of numbers;
repeat with subpath running through the D21P2 possible paths from button to target:
let cost be the D21P2 shortest sequence length for subpath at (level - 1);
if best is empty or cost is bignum less than best:
now best is cost;
now steps is steps bignum+ best;
now button is target;
[log "C: [level] [path] => [steps in bignum notation]" at INFO;]
if path <= D21P2_NUM_NUMERIC_PATHS:
now entry path in entry level in D21P2 cache is steps;
decide on steps;
To decide what number is the D21P2 button for (c - text):
if c is "0", decide on D21_NUMERIC_0;
if c is "1", decide on D21_NUMERIC_1;
if c is "2", decide on D21_NUMERIC_2;
if c is "3", decide on D21_NUMERIC_3;
if c is "4", decide on D21_NUMERIC_4;
if c is "5", decide on D21_NUMERIC_5;
if c is "6", decide on D21_NUMERIC_6;
if c is "7", decide on D21_NUMERIC_7;
if c is "8", decide on D21_NUMERIC_8;
if c is "9", decide on D21_NUMERIC_9;
if c is "A", decide on D21_A;
if c is "a", decide on D21_A;
log "FAILED TO PARSE: [c]" at ERROR;
decide on -1;
To decide what list of number is the D21P2 shortest sequence length for (t - text) with (level - number) numeric keypads:
let n be the number of characters in t;
let steps be BIGNUM_ZERO;
let button be D21_A;
repeat with i running from 1 to n:
let target be the D21P2 button for character number i in t;
let best be a list of numbers;
repeat with subpath running through the D21P2 possible paths from button to target:
let cost be the D21P2 shortest sequence length for subpath at level;
if best is empty or cost is bignum less than best:
now best is cost;
now steps is steps bignum+ best;
now button is target;
decide on steps;
Carry out entering a D21P2 line:
let target be the topic understood;
let x be the D21P2 shortest sequence length for target with (D21P2_NUMERIC_LEVELS) numeric keypads;
let y be (the substring of target from 1 to (number of characters in target - 1)) converted to bignum;
let xy be x bignum* y;
log "[x in bignum notation] * [y in bignum notation] = [xy in bignum notation]" at INFO;
now D21P2 result is D21P2 result bignum+ xy;
Before entering a blank line while D21P2 scene is happening:
say "[D21P2 result in bignum notation]";
unpush D21P2 button;
Chapter - Day 22
Day 22 is a room.
d22 is a direction. d22 has opposite outside. Index map with d22 mapped as inside.
Door 22 is a door. Door 22 is d22 of the Vortex and outside of Day 22.
Section - Part 1
D22P1 button is a part 1 button.
D22P1 button is here.
D22P1 scene is a recurring scene.
D22P1 scene begins when D22P1 button is switched on.
D22P1 scene ends when D22P1 button is switched off.
Table of Stars (continued)
Day Part Button
22 1 D22P1 button
D22P1 result is a list of number that varies.
When D22P1 scene begins:
now D22P1 result is BIGNUM_ZERO;
Entering a D22P1 line is an action applying to one topic.
Understand "[text]" as entering a D22P1 line while D22P1 scene is happening.
To decide which number is (secret - number) after (n - number) D22P1 iterations:
repeat with i running from 1 to n:
[ now secret is ((secret bignum<< 6) bignum^ secret) bignum&& mask;
now secret is ((secret bignum>> 5) bignum^ secret) bignum&& mask;
now secret is ((secret bignum<< 11) bignum^ secret) bignum&& mask;]
now secret is ((secret * 64) xor secret) bitwise-and 16777215;
now secret is ((secret / 32) xor secret)[ bitwise-and 16777215];
now secret is (((secret bitwise-and 8191) * 2048) xor secret) bitwise-and 16777215;
decide on secret;
Carry out entering a D22P1 line:
let target be the topic understood;
let t be (target understood as a number) after 2000 D22P1 iterations;
log " => [t]" at INFO;
now D22P1 result is D22P1 result bignum+ (t converted to bignum);
Before entering a blank line while D22P1 scene is happening:
say "[D22P1 result in bignum notation]";
unpush D22P1 button;
Section - Part 2
D22P2 button is a part 2 button.
D22P2 button is here.
D22P2 scene is a recurring scene.
D22P2 scene begins when D22P2 button is switched on.
D22P2 scene ends when D22P2 button is switched off.
Table of Stars (continued)
Day Part Button
22 2 D22P2 button
D22P2 prices is a list of numbers that varies.
D22P2 seen is a list of numbers that varies.
D22P2 epoch is a number that varies.
[We have numbers in the range [-9, 9], which we increase by 9 to get [0, 18]]
To decide which number is the D22P2 sequence index of (x - list of numbers) with (offset - number):
let result be 0;
let i be offset;
repeat with j running from 1 to 4:
let k be entry i in x;
now result is (result * 19) + (k + 9);
increment i;
if i > 4:
now i is 1;
decide on result + 1;
[There are 19**4 possible sequence indices.]
D22P2_NUM_SEQUENCES is always 130321.
When D22P2 scene begins:
truncate D22P2 prices to 0 entries;
extend D22P2 prices to D22P2_NUM_SEQUENCES entries;
truncate D22P2 seen to 0 entries;
extend D22P2 seen to D22P2_NUM_SEQUENCES entries;
now D22P2 epoch is 0;
Entering a D22P2 line is an action applying to one topic.
Understand "[text]" as entering a D22P2 line while D22P2 scene is happening.
To process D22P2 iterations of (secret - number):
increment D22P2 epoch;
let last price be the remainder after dividing secret by 10;
let price delta window be {0, 0, 0, 0};
let offset be 1;
repeat with i running from 1 to 2000:
now secret is ((secret * 64) xor secret) bitwise-and 16777215;
now secret is ((secret / 32) xor secret)[ bitwise-and 16777215];
now secret is (((secret bitwise-and 8191) * 2048) xor secret) bitwise-and 16777215;
let price be the remainder after dividing secret by 10;
let price delta be price - last price;
now entry offset in price delta window is price delta;
increment offset;
if offset > 4:
now offset is 1;
if i >= 4:
let j be the D22P2 sequence index of price delta window with offset;
if entry j in D22P2 seen < D22P2 epoch:
increase entry j in D22P2 prices by price;
now entry j in D22P2 seen is D22P2 epoch;
now last price is price;
Carry out entering a D22P2 line:
let target be the topic understood;
process D22P2 iterations of (target understood as a number);
Before entering a blank line while D22P2 scene is happening:
let largest be 0;
repeat with i running from 1 to D22P2_NUM_SEQUENCES:
if entry i in D22P2 prices > largest:
now largest is entry i in D22P2 prices;
say "[largest]";
now D22P2 prices is {};
now D22P2 seen is {};
unpush D22P2 button;
Chapter - Day 23
Day 23 is a room.
d23 is a direction. d23 has opposite outside. Index map with d23 mapped as inside.
Door 23 is a door. Door 23 is d23 of the Vortex and outside of Day 23.
Section - Part 1
D23P1 button is a part 1 button.
D23P1 button is here.
D23P1 scene is a recurring scene.
D23P1 scene begins when D23P1 button is switched on.
D23P1 scene ends when D23P1 button is switched off.
Table of Stars (continued)
Day Part Button
23 1 D23P1 button
D23P1 adjacent is a list of list of numbers that varies.
D23_NUM_COMPUTERS is always 676;
When D23P1 scene begins:
now D23P1 adjacent is {};
repeat with x running from 1 to D23_NUM_COMPUTERS:
let connections be a list of numbers;
add connections to D23P1 adjacent;
Entering a D23P1 line is an action applying to one topic.
Understand "[text]" as entering a D23P1 line while D23P1 scene is happening.
To decide which number is the D23P1 computer index of (name - text):
let n be the number of characters in name;
let result be 0;
let a be the ordinal of character number 1 in "a";
repeat with i running from 1 to n:
now result is (result * 26) + (the ordinal of character number i in name - a);
decide on result + 1;
D23P1_ALPHABET is always "abcdefghijklmnopqrstuvwxyz".
To decide which text is the D23P1 computer name of (index - number):
decrement index;
let x be (index / 26) + 1;
let y be (the remainder after dividing index by 26) + 1;
decide on "[character number x in D23P1_ALPHABET][character number y in D23P1_ALPHABET]";
Carry out entering a D23P1 line:
let target be the topic understood;
let x be word number 1 in target;
let y be word number 2 in target;
let xn be the D23P1 computer index of x;
let yn be the D23P1 computer index of y;
add xn to entry yn in D23P1 adjacent;
add yn to entry xn in D23P1 adjacent;
To decide what number is the D23P1 result:
let result be 0;
repeat with x running from 1 to D23_NUM_COMPUTERS:
sort entry x in D23P1 adjacent;
repeat with x running from 1 to D23_NUM_COMPUTERS:
let xn be D23P1 computer name of x;
repeat with y running through entry x in D23P1 adjacent:
if y <= x, next;
let yn be D23P1 computer name of y;
[We have a pair of connected computers (x, y)]
[Find all computers connected to x and all computers connected to y]
let zs be the intersection of already-sorted (entry x in D23P1 adjacent) and (entry y in D23P1 adjacent);
repeat with z running through zs:
if z <= y, next;
let zn be D23P1 computer name of z;
if character number 1 in xn is "t" or character number 1 in yn is "t" or character number 1 in zn is "t":
[log "[D23P1 computer name of x],[D23P1 computer name of y],[D23P1 computer name of z]" at INFO;]
increment result;
decide on result;
Before entering a blank line while D23P1 scene is happening:
say "[D23P1 result]";
unpush D23P1 button;
Section - Part 2
D23P2 button is a part 2 button.
D23P2 button is here.
D23P2 scene is a recurring scene.
D23P2 scene begins when D23P2 button is switched on.
D23P2 scene ends when D23P2 button is switched off.
Table of Stars (continued)
Day Part Button
23 2 D23P2 button
D23P2 adjacent is a list of list of numbers that varies.
D23_NUM_COMPUTERS is always 676;
When D23P2 scene begins:
now D23P2 adjacent is {};
repeat with x running from 1 to D23_NUM_COMPUTERS:
let connections be a list of numbers;
add connections to D23P2 adjacent;
Entering a D23P2 line is an action applying to one topic.
Understand "[text]" as entering a D23P2 line while D23P2 scene is happening.
To decide which number is the D23P2 computer index of (name - text):
let n be the number of characters in name;
let result be 0;
let a be the ordinal of character number 1 in "a";
repeat with i running from 1 to n:
now result is (result * 26) + (the ordinal of character number i in name - a);
decide on result + 1;
D23P2_ALPHABET is always "abcdefghijklmnopqrstuvwxyz".
To decide which text is the D23P2 computer name of (index - number):
decrement index;
let x be (index / 26) + 1;
let y be (the remainder after dividing index by 26) + 1;
decide on "[character number x in D23P2_ALPHABET][character number y in D23P2_ALPHABET]";
Carry out entering a D23P2 line:
let target be the topic understood;
let x be word number 1 in target;
let y be word number 2 in target;
let xn be the D23P2 computer index of x;
let yn be the D23P2 computer index of y;
add xn to entry yn in D23P2 adjacent;
add yn to entry xn in D23P2 adjacent;
[
To decide what list of list of numbers is the D23P2 maximum cliques:
let smaller cliques be a list of list of numbers;
let larger cliques be a list of list of numbers;
repeat with x running from 1 to D23_NUM_COMPUTERS:
repeat with y running through entry x in D23P2 adjacent:
if y < x, next;
let clique be a list of numbers;
add x to clique;
add y to clique;
add clique to larger cliques;
let clique size be 1;
while larger cliques is not empty:
now smaller cliques is larger cliques;
now larger cliques is {};
increment clique size;
log "S = [clique size] ([number of entries in smaller cliques])" at INFO;
let n be the number of entries in smaller cliques;
repeat with i running from 1 to n:
let y be entry clique size in entry i in smaller cliques;
repeat with z running through entry y in D23P2 adjacent:
if z < y, next;
let connected be true;
repeat with x running through entry i in smaller cliques:
if z is not in already-sorted entry x in D23P2 adjacent:
now connected is false;
break;
if connected is false, break;
if connected is false, next;
let larger clique be a list of numbers;
repeat with x running through entry i in smaller cliques:
add x to larger clique;
add z to larger clique;
add larger clique to larger cliques;
decide on smaller cliques;
]
To decide if (a - list of numbers) and (b - list of numbers) form a D23P2 clique:
repeat with x running through a:
repeat with y running through b:
if y is not in already-sorted entry x in D23P2 adjacent:
decide no;
decide yes;
To decide what list of list of numbers is the D23P2 maximum cliques:
let smaller cliques be a list of list of numbers;
let larger cliques be a list of list of numbers;
repeat with x running from 1 to D23_NUM_COMPUTERS:
repeat with y running through entry x in D23P2 adjacent:
if y < x, next;
let clique be a list of numbers;
add x to clique;
add y to clique;
add clique to larger cliques;
let clique size be 1;
while larger cliques is not empty:
now smaller cliques is larger cliques;
now larger cliques is {};
now clique size is clique size * 2;
log "S = [clique size] ([number of entries in smaller cliques])" at INFO;
let n be the number of entries in smaller cliques;
repeat with i running from 1 to n:
log "i = [i] ([number of entries in larger cliques])" at INFO every 100 of i;
let y be entry clique size in entry i in smaller cliques;
let candidates be entry (entry 1 in entry i in smaller cliques) in D23P2 adjacent;
repeat with j running from 2 to clique size:
if the number of entries in candidates < clique size, break;
now candidates is the intersection of already-sorted candidates and entry (entry j in entry i in smaller cliques) in D23P2 adjacent;
[log "C: [entry i in smaller cliques in brace notation] // [candidates in brace notation]" at INFO;]
if the number of entries in candidates < clique size, next;
let predecessor be a list of numbers;
add y to predecessor;
extend predecessor to clique size entries;
let start be the lower bound index of predecessor in smaller cliques;
repeat with j running from start to n:
if entry 1 in entry j in smaller cliques <= y, next;
let survivors be the intersection of already-sorted candidates and entry j in smaller cliques;
[if entry i in smaller cliques and entry j in smaller cliques form a D23P2 clique:]
if the number of entries in survivors is clique size:
let larger clique be a list of numbers;
add entry i in smaller cliques to larger clique;
add entry j in smaller cliques to larger clique;
add larger clique to larger cliques;
log "(switching to +1)" at INFO;
now clique size is the number of entries in entry 1 in smaller cliques - 1;
now larger cliques is smaller cliques;
while larger cliques is not empty:
now smaller cliques is larger cliques;
now larger cliques is {};
increment clique size;
log "S = [clique size] ([number of entries in smaller cliques])" at INFO;
let n be the number of entries in smaller cliques;
repeat with i running from 1 to n:
let y be entry clique size in entry i in smaller cliques;
repeat with z running through entry y in D23P2 adjacent:
if z < y, next;
let connected be true;
repeat with x running through entry i in smaller cliques:
if z is not in already-sorted entry x in D23P2 adjacent:
now connected is false;
break;
if connected is false, break;
if connected is false, next;
let larger clique be a list of numbers;
repeat with x running through entry i in smaller cliques:
add x to larger clique;
add z to larger clique;
add larger clique to larger cliques;
decide on smaller cliques;
Before entering a blank line while D23P2 scene is happening:
repeat with x running from 1 to D23_NUM_COMPUTERS:
sort entry x in D23P2 adjacent;
let cliques be the D23P2 maximum cliques;
repeat with c running through cliques:
log "[c in brace notation]" at INFO;
let result be "[D23P2 computer name of entry 1 in c]";
repeat with i running from 2 to the number of entries in c:
now result is "[result],[D23P2 computer name of entry i in c]";
say "[result][line break]";
unpush D23P2 button;
Test d23example with "kh-tc / qp-kh / de-cg / ka-co / yn-aq / qp-ub / cg-tb / vc-aq / tb-ka / wh-tc / yn-cg / kh-ub / ta-co / de-co / tc-td / tb-wq / wh-td / ta-ka / td-qp / aq-cg / wq-ub / ub-vc / de-ta / wq-aq / wq-vc / wh-yn / ka-de / kh-ta / co-tc / wh-qp / tb-vc / td-yn / /";
Chapter - Day 24
Day 24 is a room.
d24 is a direction. d24 has opposite outside. Index map with d24 mapped as inside.
Door 24 is a door. Door 24 is d24 of the Vortex and outside of Day 24.
Section - Part 1
D24P1 button is a part 1 button.
D24P1 button is here.
D24P1 scene is a recurring scene.
D24P1 scene begins when D24P1 button is switched on.
D24P1 scene ends when D24P1 button is switched off.
Table of Stars (continued)
Day Part Button
24 1 D24P1 button
D24P1 names is a list of text that varies.
D24P1 values is a list of number that varies.
[(result, a, b, op)]
D24P1 dependencies is a list of list of numbers that varies.
D24P1_OP_AND is always 1.
D24P1_OP_OR is always 2.
D24P1_OP_XOR is always 3.
D24P1 names index is a list of list of numbers that varies.
D24P1 initial values entered is a truth state that varies.
D24P1_HASH_BUCKETS is always 128.
When D24P1 scene begins:
now D24P1 names is {};
now D24P1 values is {};
now D24P1 dependencies is {};
now D24P1 names index is {};
now D24P1 initial values entered is false;
repeat with i running from 1 to D24P1_HASH_BUCKETS:
let bucket be a list of numbers;
add bucket to D24P1 names index;
enable punctuation stripping;
Entering a D24P1 line is an action applying to one topic.
Understand "[text]" as entering a D24P1 line while D24P1 scene is happening.
To decide what number is the D24P1 hash value of (x - text):
let h be 0;
let n be the number of characters in x;
repeat with i running from 1 to n:
now h is (h * 31) + (the ordinal of character number i in x);
decide on h;
To insert D24P1 name (x - text):
let h be the D24P1 hash value of x;
let i be (the remainder after dividing h by D24P1_HASH_BUCKETS) + 1;
add x to D24P1 names;
let n be the number of entries in D24P1 names;
add n to entry i in D24P1 names index;
To decide what number is the D24P1 name index of (x - text):
let h be the D24P1 hash value of x;
let i be (the remainder after dividing h by D24P1_HASH_BUCKETS) + 1;
repeat with j running through entry i in D24P1 names index:
if entry j in D24P1 names is x:
decide on j;
decide on 0;
To decide what number is the maybe-inserted D24P1 name index of (x - text):
let h be the D24P1 hash value of x;
let i be (the remainder after dividing h by D24P1_HASH_BUCKETS) + 1;
repeat with j running through entry i in D24P1 names index:
if entry j in D24P1 names is x:
decide on j;
add x to D24P1 names;
let n be the number of entries in D24P1 names;
add n to entry i in D24P1 names index;
decide on n;
Carry out entering a D24P1 line:
let words be the words of the topic understood;
if D24P1 initial values entered is false:
insert D24P1 name entry 1 in words;
add entry 2 in words understood as a number to D24P1 values;
else:
let entry be a list of numbers;
add the maybe-inserted D24P1 name index of entry 5 in words to entry; [result]
add the maybe-inserted D24P1 name index of entry 1 in words to entry; [a]
add the maybe-inserted D24P1 name index of entry 3 in words to entry; [b]
let op be entry 2 in words in upper case;
if op is "AND":
add D24P1_OP_AND to entry;
else if op is "OR":
add D24P1_OP_OR to entry;
else if op is "XOR":
add D24P1_OP_XOR to entry;
else:
log "BAD OPERATION [op]" at ERROR;
add entry to D24P1 dependencies;
add -1 to D24P1 values;
To decide what number is the D24P1 dependency index of (index - number):
let entry be a list of numbers;
add index to entry;
add 0 to entry;
add 0 to entry;
add 0 to entry;
let i be the lower bound index of entry in D24P1 dependencies;
let n be the number of entries in D24P1 dependencies;
if i <= n and entry 1 in entry i in D24P1 dependencies is index:
decide on i;
decide on 0;
To decide what list of numbers is the D24P1 topological sort:
let added be a list of truth states;
let visited be a list of truth states;
let n be the number of entries in D24P1 names;
let stack be a list of numbers;
repeat with i running from 1 to n:
add false to added;
add false to visited;
add i to stack;
let order be a list of numbers;
while stack is not empty:
let m be the number of entries in stack;
let i be entry m in stack;
if entry i in visited is false:
let j be the D24P1 dependency index of i;
if j > 0:
add entry 2 in entry j in D24P1 dependencies to stack;
add entry 3 in entry j in D24P1 dependencies to stack;
else:
[we don't need to compute initial values]
now entry i in added is true;
now entry i in visited is true;
else:
truncate stack to m - 1 entries;
if entry i in added is false:
add i to order;
now entry i in added is true;
decide on order;
To perform the D24P1 computation:
sort D24P1 dependencies;
let order be the D24P1 topological sort;
let offset be number of entries in D24P1 values - number of entries in D24P1 dependencies;
repeat with ii running through order:
let i be ii - offset;
let result index be entry 1 in entry i in D24P1 dependencies;
let a index be entry 2 in entry i in D24P1 dependencies;
let b index be entry 3 in entry i in D24P1 dependencies;
let op be entry 4 in entry i in D24P1 dependencies;
let a be entry a index in D24P1 values;
let b be entry b index in D24P1 values;
let result be -1;
if op is D24P1_OP_AND:
now result is a bitwise-and b;
else if op is D24P1_OP_OR:
now result is a bitwise-or b;
else if op is D24P1_OP_XOR:
now result is a xor b;
else:
log "UNKNOWN OP [op]" at ERROR;
now entry result index in D24P1 values is result;
To decide what list of numbers is the D24P1 result:
perform the D24P1 computation;
let result be {1};
let i be 0;
let word be 0;
let bit be 0;
while true is true:
let name be "[i]";
if i < 10:
now name is "0[name]";
now name is "z[name]";
let j be the D24P1 name index of name;
if j is 0, break;
let k be entry j in D24P1 values;
increase word by k * (2 to the power of bit);
if bit is 15:
add word to result;
now bit is 0;
now word is 0;
else:
increment bit;
increment i;
if word is not 0 or the number of entries in result is 1:
add word to result;
decide on result;
Before entering a blank line while D24P1 scene is happening:
if D24P1 initial values entered is false:
now D24P1 initial values entered is true;
else:
say "[D24P1 result in bignum notation]";
disable punctuation stripping;
unpush D24P1 button;
Section - Part 2
D24P2 button is a part 2 button.
D24P2 button is here.
D24P2 scene is a recurring scene.
D24P2 scene begins when D24P2 button is switched on.
D24P2 scene ends when D24P2 button is switched off.
Table of Stars (continued)
Day Part Button
24 2 D24P2 button
[
This solution is very much tailored to my input and not a general-purpose solution.
Sorry. :(
]
D24P2 initial values entered is a truth state that varies.
[(result, a, b, op)]
D24P2 dependencies is a list of list of text that varies.
D24P2 swaps is a list of text that varies.
When D24P2 scene begins:
now D24P2 dependencies is {};
now D24P2 initial values entered is false;
enable punctuation stripping;
Entering a D24P2 line is an action applying to one topic.
Understand "[text]" as entering a D24P2 line while D24P2 scene is happening.
Carry out entering a D24P2 line:
let words be the words of (the topic understood in lower case);
if D24P2 initial values entered is true:
let entry be a list of text;
add entry 5 in words to entry; [result]
add entry 1 in words to entry; [a]
add entry 3 in words to entry; [b]
add entry 2 in words to entry; [op]
add entry to D24P2 dependencies;
To apply the D24P2 swap of (x - text) with (y - text):
let n be the number of entries in D24P2 dependencies;
repeat with i running from 1 to n:
if entry 1 in entry i in D24P2 dependencies is x:
now entry 1 in entry i in D24P2 dependencies is y;
else if entry 1 in entry i in D24P2 dependencies is y:
now entry 1 in entry i in D24P2 dependencies is x;
To decide what text is the D24P2 find from (src - text) and (dst - text) with (op - text) to (expect - text):
let potential swaps be a list of text;
let n be the number of entries in D24P2 dependencies;
repeat with i running from 1 to n:
if entry 4 in entry i in D24P2 dependencies is not op, next;
let c be entry 1 in entry i in D24P2 dependencies;
let a be entry 2 in entry i in D24P2 dependencies;
let b be entry 3 in entry i in D24P2 dependencies;
if (src is a and dst is b) or (dst is a and src is b):
if expect is not "" and c is not expect:
add c to D24P2 swaps;
add expect to D24P2 swaps;
decide on "";
decide on c;
if expect is "" or c is expect:
if src is a:
add b to potential swaps;
add dst to potential swaps;
if src is b:
add a to potential swaps;
add dst to potential swaps;
if dst is a:
add b to potential swaps;
add src to potential swaps;
if dst is b:
add a to potential swaps;
add src to potential swaps;
if the number of entries in potential swaps is not 2:
log "FAILED TO DETERMINE SWAP: [potential swaps in brace notation]" at ERROR;
add potential swaps to D24P2 swaps;
decide on "";
To decide if D24P2 needs more swaps:
let z be the D24P2 find from "x00" and "y00" with "xor" to "z00";
if z is "", decide yes;
let full carry a be the D24P2 find from "x00" and "y00" with "and" to "";
if full carry a is "", decide yes;
repeat with n running through {"01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44"}:
let x be "x[n]";
let y be "y[n]";
let half sum b be the D24P2 find from x and y with "xor" to "";
if half sum b is "", decide yes;
now z is the D24P2 find from full carry a and half sum b with "xor" to "z[n]";
if z is "", decide yes;
let half carry b be the D24P2 find from x and y with "and" to "";
if half carry b is "", decide yes;
let full sum b be the D24P2 find from full carry a and half sum b with "and" to "";
if full sum b is "", decide yes;
now full carry a is the D24P2 find from full sum b and half carry b with "or" to "";
if full carry a is "", decide yes;
decide no;
To decide what text is the D24P2 result:
while D24P2 needs more swaps:
let n be the number of entries in D24P2 swaps;
if n is 8, break;
apply the D24P2 swap of (entry n - 1 in D24P2 swaps) with (entry n in D24P2 swaps);
sort D24P2 swaps;
let result be entry 1 in D24P2 swaps;
repeat with i running from 2 to the number of entries in D24P2 swaps:
now result is "[result],[entry i in D24P2 swaps]";
decide on result;
Before entering a blank line while D24P2 scene is happening:
if D24P2 initial values entered is false:
now D24P2 initial values entered is true;
else:
say "[D24P2 result][line break]";
now D24P2 dependencies is {};
now D24P2 swaps is {};
disable punctuation stripping;
unpush D24P2 button;
Chapter - Day 25
Day 25 is a room.
d25 is a direction. d25 has opposite outside. Index map with d25 mapped as inside.
Door 25 is a door. Door 25 is d25 of the Vortex and outside of Day 25.
Section - Part 1
D25P1 button is a part 1 button.
D25P1 button is here.
D25P1 scene is a recurring scene.
D25P1 scene begins when D25P1 button is switched on.
D25P1 scene ends when D25P1 button is switched off.
Table of Stars (continued)
Day Part Button
25 1 D25P1 button
D25P1 paragraph is a list of text that varies.
D25P1 locks is a list of list of numbers that varies.
D25P1 keys is a list of list of numbers that varies.
D25P1_PINS is always 5.
D25P1_DEPTH is always 5.
When D25P1 scene begins:
enable raw input;
After reading a raw input while D25P1 scene is happening:
let line be the raw input;
if line is "":
if D25P1 paragraph is empty:
complete the D25P1 computation;
else:
process the D25P1 paragraph;
now D25P1 paragraph is {};
else:
add line to D25P1 paragraph;
To process the D25P1 paragraph:
let search be character number 1 in entry 1 in D25P1 paragraph;
let cuts be a list of numbers;
repeat with i running from 1 to D25P1_PINS:
let cut be 1;
while cut <= D25P1_DEPTH:
if character number i in entry (cut + 1) in D25P1 paragraph is not search:
break;
increment cut;
add cut to cuts;
if search is "#":
add cuts to D25P1 locks;
else:
add cuts to D25P1 keys;
To decide if (key - list of number) D25P1 fits (lock - list of numbers):
repeat with i running from 1 to D25P1_PINS:
if entry i in lock > entry i in key:
decide no;
decide yes;
To complete the D25P1 computation:
log "L = [number of entries in D25P1 locks]" at INFO;
log "K = [number of entries in D25P1 keys]" at INFO;
let result be 0;
repeat with lock running through D25P1 locks:
repeat with key running through D25P1 keys:
if key D25P1 fits lock, increment result;
say "[result]";
disable raw input;
unpush D25P1 button;
Section - Part 2
D25P2 button is a part 2 button.
D25P2 button is here.
Table of Stars (continued)
Day Part Button
25 2 D25P2 button
To decide if the D25P2 chronicle is complete:
repeat through the Table of Stars:
if button entry is not D25P2 button and button entry is incomplete:
decide no;
decide yes;
Check switching on the D25P2 button:
if not the D25P2 chronicle is complete:
say "You can't press that yet.";
stop the action;
Report switching on the D25P2 button:
now D25P2 button is complete;
say "You win![paragraph break][star progress]";
end the story finally;
Chapter - Implementation
Section - Text
To decide what number is the ordinal of character number (i - number) in (t - text):
(- CharacterOrdinal({-by-reference:t}, {i}) -).
Include (-
[ CharacterOrdinal txt i cp p ch;
if (txt==0) return 0;
cp = txt-->0; p = TEXT_TY_Temporarily_Transmute(txt);
if ((i<=0) || (i>TEXT_TY_CharacterLength(txt))) ch = 0;
else ch = BlkValueRead(txt, i-1);
TEXT_TY_Untransmute(txt, p, cp);
return ch;
]
-).
To decide what text is (X - text) + (Y - text) (this is concatenation):
decide on "[X][Y]".
To decide what text is the str of (X - number) (this is str):
decide on "[X]".
To decide which list of text is the words of (strings - text):
let result be a list of text;
repeat with i running from 1 to the number of words in strings:
add word number i in strings to the result;
decide on result.
To decide which list of text is (t - text) split by any of (delimiters - list of text):
let result be a list of text;
let word be "";
let n be the number of characters in t;
let i be 1;
while i <= n:
let c be character number i in t;
if c is listed in delimiters:
if word is not "":
add word to result;
now word is "";
else:
now word is "[word][c]";
increment i;
if word is not "":
add word to result;
decide on result;
To decide which text is the substring of (t - text) from (start - number) to (end - number):
let result be "";
repeat with i running from start to end:
now result is "[result][character number i in t]";
decide on result;
To decide which text is the suffix of (t - text) from (start - number):
let end be the number of characters in t;
decide on the substring of t from start to end;
To decide which number is the digit value of (c - text):
if c is "0", decide on 0;
if c is "1", decide on 1;
if c is "2", decide on 2;
if c is "3", decide on 3;
if c is "4", decide on 4;
if c is "5", decide on 5;
if c is "6", decide on 6;
if c is "7", decide on 7;
if c is "8", decide on 8;
if c is "9", decide on 9;
decide on -1;
Definition: a text is a digit if the digit value of it is not -1.
Section - More Regular Expressions
To decide which list of text is the regex matches of (pattern - text) on (data - text):
let result be a list of text;
while data exactly matches the regular expression "^.*?([pattern])(.*)$":
add the text matching subexpression 1 to result;
now data is the text matching subexpression 2;
decide on result.
Section - Numbers
MAX_I32 is always 2147483647.
Divisibility relates a number (called x) to a number (called y) when the remainder after dividing x by y is 0.
The verb to be divisible by means the divisibility relation.
To decide what number is (input - text) understood as a number (this is parse number):
let reserve text be the substituted form of "[the players command]";
change the text of the player's command to input;
if the players command matches "[number]":
change the text of the player's command to reserve text;
decide on the number understood;
change the text of the player's command to reserve text;
decide on 0.
To decide what number is the integer absolute value of (x - number):
if x < 0:
decide on 0 - x;
decide on x.
To decide what number is (x - number) to the power of (y - number):
let result be 1;
repeat with i running from 1 to y:
now result is result * x;
decide on result;
To decide what number is the greatest common divisor of (a - number) and (b - number):
while b is not 0:
let tmp be b;
now b is the remainder after dividing a by b;
now a is tmp;
decide on a;
To decide what number is the gcd of (a - number) and (b - number):
decide on the greatest common divisor of a and b;
To decide what number is (x - number) xor (y - number):
(- ({x} | {y}) & (~({x} & {y})) -).
To decide what number is (x - number) bitwise-and (y - number):
(- ({x} & {y}) -).
To decide what number is (x - number) bitwise-or (y - number):
(- ({x} | {y}) -).
Section - 32 bit integers
MAX_U16 is always 65535.
[Data representation:
array u32 {
w1: u16
w2: u16
};
N is (w1 << 16) | w2]
To decide what list of number is (x - number) u16* (y - number):
let xh be x / 256;
let xl be the remainder after dividing x by 256;
let yh be y / 256;
let yl be the remainder after dividing y by 256;
let result be {0, 0};
increase entry 2 of result by xl * yl;
let tmp be xl * (yh * 256);
increase entry 2 of result by the remainder after dividing tmp by 65536;
increase entry 1 of result by tmp / 65536;
now tmp is (xh * 256) * yl;
increase entry 2 of result by the remainder after dividing tmp by 65536;
increase entry 1 of result by tmp / 65536;
now tmp is xh * yh;
increase entry 1 of result by tmp;
decide on result;
Section - Bignums
[Data representation:
{sign, word1, word2, ...}
sign : {-1, 1}
wordN : {0...65535}
represents the number sign * word1 | (word2 << 16) | ...
special case: {-1, 0} is forbidden, zero is written {1, 0}
]
BIGNUM_FORBIDDEN_ZERO is always {-1, 0}.
BIGNUM_ZERO is always {1, 0}.
BIGNUM_ONE is always {1, 1}.
To decide if (n - list of number) is a valid bignum:
if number of entries of n < 2, decide no;
if n is BIGNUM_FORBIDDEN_ZERO, decide no;
let sign be entry 1 of n;
if sign is not 1 and sign is not -1, decide no;
repeat with i running from 2 to the number of entries in n:
let word be entry i of n;
if word < 0 or word > MAX_U16, decide no;
decide yes;
Comparison result is a kind of value. The comparison results are smaller, equal and larger.
To decide what comparison result is (x - list of number) bignum magnitude compared to (y - list of number):
let xn be the number of entries in x;
let yn be the number of entries in y;
if xn > yn, decide on larger;
if xn < yn, decide on smaller;
let i be xn;
while i >= 2:
let xw be entry i of x;
let yw be entry i of y;
if xw > yw, decide on larger;
if xw < yw, decide on smaller;
decrement i;
decide on equal;
To decide what comparison result is (x - list of number) bignum compared to (y - list of number):
[Check if numbers have the same sign]
let xs be entry 1 of x;
let ys be entry 1 of y;
if xs > ys, decide on larger;
if xs < ys, decide on smaller;
[If both numbers are negative, the larger one will have the smaller magnitude]
if xs is -1:
decide on y bignum magnitude compared to x;
decide on x bignum magnitude compared to y;
[<]
bignum less than relates a list of numbers (called x) to a list of numbers (called y) when x bignum compared to y is smaller.
The verb to be bignum less than means the bignum less than relation.
[<=]
bignum at most relates a list of numbers (called x) to a list of numbers (called y) when x bignum compared to y is not larger.
The verb to be bignum at most means the bignum at most relation.
[>=]
bignum at least relates a list of numbers (called x) to a list of numbers (called y) when x bignum compared to y is not smaller.
The verb to be bignum at least means the bignum at least relation.
[>]
bignum greater than relates a list of numbers (called x) to a list of numbers (called y) when x bignum compared to y is larger.
The verb to be bignum greater than means the bignum greater than relation.
To decide what list of number is (x - list of number) bignum+ (y - list of number):
let xs be entry 1 of x;
let ys be entry 1 of y;
let result sign be 1;
let operation sign be 1;
if xs is -1 and ys is -1: [-|x| + -|y| = -(|x| + |y|)]
now result sign is -1;
else if xs is -1 and ys is 1: [-|x| + |y| = -(|x| - |y|)]
now result sign is -1;
now operation sign is -1;
else if xs is 1 and ys is -1: [|x| - |y|]
now operation sign is -1;
[else: |x| + |y|]
[Subtraction routine:]
if operation sign is -1:
[Make sure we have x > y, by x-y = -(y-x)]
if x bignum magnitude compared to y is smaller:
let tmp be y;
now y is x;
now x is tmp;
now result sign is result sign * -1;
let result be a list of numbers;
add result sign to result;
let carry be 0;
let xn be the number of entries in x;
let yn be the number of entries in y;
[Since x > y, xn >= yn, so we can unconditionally read x's words]
repeat with i running from 2 to xn:
let xw be entry i of x;
let yw be 0;
if i <= yn:
now yw is entry i of y;
let zw be xw - yw + carry;
now carry is 0;
while zw < 0:
decrement carry;
increase zw by 65536;
add zw to result;
[We might end up with something like {1, 0, 0, 0, 0}, so we need to trim that down to {1, 0}]
let n be the number of entries in result;
while n > 2 and entry n in result is 0:
decrement n;
truncate result to n entries;
if result is BIGNUM_FORBIDDEN_ZERO, decide on BIGNUM_ZERO;
decide on result;
[Addition routine:]
let result be a list of numbers;
add result sign to result;
let carry be 0;
let xn be the number of entries in x;
let yn be the number of entries in y;
let i be 2;
while i <= xn or i <= yn:
let xw be 0;
if i <= xn:
now xw is entry i of x;
let yw be 0;
if i <= yn:
now yw is entry i of y;
let zw be xw + yw + carry;
now carry is 0;
while zw > MAX_U16:
increment carry;
decrease zw by 65536;
add zw to result;
increment i;
if carry > 0, add carry to result;
if result is BIGNUM_FORBIDDEN_ZERO, decide on BIGNUM_ZERO;
decide on result;
To decide what list of number is (x - list of number) bignum- (y - list of number):
let z be y;
now entry 1 of z is (entry 1 of z) * -1;
decide on x bignum+ z;
To decide what list of number is (x - list of number) bignum* (y - list of number):
let xs be entry 1 of x;
let ys be entry 1 of y;
let result be a list of numbers;
add xs * ys to result;
let xn be the number of entries in x;
let yn be the number of entries in y;
[
x has xn - 1 digits, y has yn - 1 digits
so x * y will have at most (xn - 1) + (yn - 1) digits
and we need 1 more list entry for the sign
]
extend result to xn + yn - 1 entries;
repeat with i running from 2 to xn:
repeat with j running from 2 to yn:
let tmp be (entry i in x) u16* (entry j in y);
let k be i + j - 2;
let r be entry k of result + entry 2 in tmp;
let carry be r / 65536;
now entry k of result is (r - (carry * 65536));
now r is (entry k + 1 of result) + (entry 1 in tmp) + carry;
now carry is r / 65536;
now entry k + 1 of result is (r - (carry * 65536));
if carry > 0:
increase entry k + 2 of result by carry;
[We might end up with something like {1, 0, 0, 0, 0}, so we need to trim that down to {1, 0}]
let n be the number of entries in result;
while n > 2 and entry n in result is 0:
decrement n;
truncate result to n entries;
if result is BIGNUM_FORBIDDEN_ZERO, decide on BIGNUM_ZERO;
decide on result;
To decide what list of numbers is the bignumu8 internal representation of (x - list of numbers):
let result be a list of numbers;
let n be the number of entries in x;
repeat with i running from 2 to n:
let w be entry i in x;
add the remainder after dividing w by 256 to result;
add w / 256 to result;
now n is the number of entries in result;
if entry n in result is 0:
truncate result to n - 1 entries;
decide on result;
To decide what list of numbers is (x - list of numbers) bignum/ (y - number):
if y < -255 or y > 255:
decide on x bignum/ (y converted to bignum);
let result be a list of numbers;
let sign be entry 1 of x;
if y < 0:
now sign is 0 - sign;
now y is 0 - y;
add sign to result;
let Q be a list of numbers;
let i be the number of entries in x;
let r be 0;
while i >= 2:
increase r by entry i of x;
let Q hat be r / y;
add Q hat to Q;
decrease r by (Q hat * y);
now r is r * 65536;
decrement i;
reverse Q;
add Q to result;
let n be the number of entries in result;
while n > 2 and entry n in result is 0:
decrement n;
truncate result to n entries;
decide on result;
To decide what list of numbers is (x - list of numbers) bignum/ (y - list of numbers):
if y is BIGNUM_ZERO:
log "BROKEN: division by zero" at ERROR;
decide on BIGNUM_ZERO;
let U be the bignumu8 internal representation of x;
add 0 to U;
let V be the bignumu8 internal representation of y;
let n be the number of entries in V;
if n is 1:
decide on x bignum/ (entry 1 in y * entry 2 in y);
let m be the (number of entries in U - n) - 1;
[log "m=[m] n=[n]" at INFO;]
if m < 0, decide on BIGNUM_ZERO;
[log "U=[U in brace notation]" at INFO;
log "V=[V in brace notation]" at INFO;]
[B is always 256]
[Normalize V]
let D be 1;
while entry n in V < 128:
now D is D * 2;
let carry be 0;
repeat with i running from 1 to n:
let v digit be (entry i in V * 2) + carry;
now carry is v digit / 256;
now entry i in V is the remainder after dividing v digit by 256;
[log "V'=[V in brace notation]" at INFO;
log "D=[D]" at INFO;]
let carry be 0;
[Normalize U]
repeat with i running from 1 to n + m:
let u digit be (entry i in U * D) + carry;
now carry is u digit / 256;
now entry i in U is the remainder after dividing u digit by 256;
now entry n + m + 1 in U is carry;
[log "U'=[U in brace notation]" at INFO;]
[Quotient loop]
let Q be a list of numbers;
let j be m;
while j >= 0:
[Estimate Q hat, then correct the estimate]
[log "D3 [j]" at INFO;]
let tmp be (entry n + j + 1 in U * 256) + (entry n + j in U);
let Q hat be tmp / entry n in V;
let R hat be the remainder after dividing tmp by entry n in V;
[log " [Q hat] [R hat]" at INFO;]
if Q hat is 256 or Q hat * entry n - 1 in V > (R hat * 256) + entry n - 1 + j in U:
decrement Q hat;
increase R hat by entry n in V;
[log " [Q hat] [R hat]" at INFO;]
while (R hat < 256) and (Q hat is 256 or Q hat * entry n - 1 in V > (R hat * 256) + entry n - 1 + j in U):
decrement Q hat;
increase R hat by entry n in V;
[log " [Q hat] [R hat]" at INFO;]
[Multiply and subtract]
[log "D4 [Q hat] [R hat]" at INFO;]
let carry be 0;
if Q hat is not 0:
repeat with i running from 1 to n:
let v digit be entry i in V;
let qv be v digit * Q hat;
[log " [i] [v digit] [qv] [entry j + i in U]" at INFO;]
let u digit be ((entry j + i in U) - qv) - carry;
now carry is 0;
while u digit < 0:
increase u digit by 256;
increment carry;
now entry j + i in U is u digit;
let u digit be (entry j + n + 1 in U) - carry;
now carry is 0;
while u digit < 0:
increase u digit by 256;
increment carry;
now entry j + n + 1 in U is u digit;
[log "U=[U in brace notation]" at INFO;]
[Correct negative results]
[log "D56 [carry]" at INFO;]
if carry > 0:
decrement Q hat;
now carry is 0;
repeat with i running from 0 to n - 1:
let v digit be entry i + 1 in V;
let u digit be (entry j + i + 1 of U) + v digit + carry;
now carry is 0;
while u digit > 256:
decrease u digit by 256;
increment carry;
now entry j + i + 1 of U is u digit;
increase entry n + j + 1 of U by carry;
add Q hat to Q;
decrement j;
reverse Q;
[log "Q=[Q in brace notation]" at INFO;]
let result be a list of numbers;
add entry 1 of x * entry 1 of y to result;
repeat with i running from 1 to the number of entries in Q:
if i is odd:
add entry i in Q to result;
else:
increase entry (i / 2) + 1 in result by (entry i in Q) * 256;
now n is the number of entries in result;
while n > 2 and entry n in result is 0:
decrement n;
truncate result to n entries;
if result is BIGNUM_FORBIDDEN_ZERO, decide on BIGNUM_ZERO;
decide on result;
To decide what list of number is (x - list of number) bignum<< (shift - number):
if x is BIGNUM_ZERO, decide on x;
let result be a list of number;
add entry 1 in x to result;
while shift >= 16:
add 0 to result;
decrease shift by 16;
let carry be 0;
let n be the number of entries in x;
let p be 2 to the power of shift;
repeat with i running from 2 to n:
let tmp be ((entry i in x) * p) + carry;
add the remainder after dividing tmp by 65536 to result;
now carry is tmp / 65536;
if carry < 0:
log "OVERFLOW" at ERROR;
if carry is not 0:
add carry to result;
decide on result;
To decide what list of number is (x - list of number) bignum>> (shift - number):
let result be a list of number;
add entry 1 in x to result;
let i be 2;
while shift >= 16:
increment i;
decrease shift by 16;
let n be the number of entries in x;
let p be 2 to the power of shift;
let q be 65536 / p;
while i <= n:
let tmp be (entry i in x) / p;
if i + 1 <= n:
increase tmp by the (remainder after dividing (entry i + 1 in x) by p) * q;
add tmp to result;
increment i;
now n is the number of entries in result;
while n > 2 and entry n in result is 0:
decrement n;
truncate result to n entries;
decide on result;
To decide what list of number is (x - list of number) bignum^ (y - list of number):
let result be a list of number;
add (entry 1 of x) * (entry 1 of y) to result;
let i be 2;
let n be the number of entries in x;
let m be the number of entries in y;
while i <= n and i <= m:
add (entry i in x) xor (entry i in y) to result;
increment i;
while i <= n:
add entry i in x to result;
increment i;
while i <= m:
add entry i in y to result;
increment i;
decide on result;
To decide what list of number is (x - list of number) bignum&& (y - list of number):
let result be a list of number;
add (entry 1 of x) * (entry 1 of y) to result;
let i be 2;
let n be the number of entries in x;
let m be the number of entries in y;
while i <= n and i <= m:
add (entry i in x) bitwise-and (entry i in y) to result;
increment i;
decide on result;
To decide what list of number is (x - number) converted to bignum:
let sign be 1;
if x < 0:
now sign is -1;
now x is x * -1;
let high be x / 65536;
let low be remainder after dividing x by 65536;
let result be a list of numbers;
add sign to result;
add low to result;
if high > 0, add high to result;
decide on result;
To decide what number is (x - list of number) converted from bignum:
let sign be entry 1 of x;
let low be entry 2 of x;
let high be entry 3 of x;
decide on ((high * 65536) + low) * sign;
BIGNUM_TEN is always {1, 10}.
BIGNUM_1e1 is always {1, 10}.
BIGNUM_1e2 is always {1, 100}.
BIGNUM_1e3 is always {1, 1000}.
BIGNUM_1e4 is always {1, 10000}.
BIGNUM_1e5 is always {1, 34464, 1}.
BIGNUM_1e6 is always {1, 16960, 15}.
BIGNUM_1e7 is always {1, 38528, 152}.
BIGNUM_1e8 is always {1, 57600, 1525}.
BIGNUM_1e9 is always {1, 51712, 15258}.
BIGNUM_1e10 is always {1, 58368, 21515, 2}.
BIGNUM_1e11 is always {1, 59392, 18550, 23}.
BIGNUM_1e12 is always {1, 4096, 54437, 232}.
BIGNUM_1e13 is always {1, 40960, 20082, 2328}.
BIGNUM_1e14 is always {1, 16384, 4218, 23283}.
BIGNUM_1e15 is always {1, 32768, 42182, 36222, 3}.
BIGNUM_1e16 is always {1, 0, 28609, 34546, 35}.
BIGNUM_1e17 is always {1, 0, 23946, 17784, 355}.
BIGNUM_1e18 is always {1, 0, 42852, 46771, 3552}.
BIGNUM_1e19 is always {1, 0, 35304, 8964, 35527}.
To decide what list of number is (x - text) converted to bignum:
[fast path: parse as a 32-bit integer]
if the number of characters in x <= 9:
decide on x understood as a number converted to bignum;
[slow path]
let result be BIGNUM_ZERO;
let i be 1;
if character number i in x is "-":
now entry 1 of result is -1;
increment i;
let n be the number of characters in x;
while n - i >= 3:
now result is result bignum* BIGNUM_1e4;
let quartet be "[character number i in x][character number i + 1 in x][character number i + 2 in x][character number i + 3 in x]";
let tmp be {1, 0};
now entry 2 of tmp is quartet understood as a number;
now result is result bignum+ tmp;
increase i by 4;
while i <= n:
now result is result bignum* BIGNUM_TEN;
let tmp be {1, 0};
now entry 2 of tmp is the digit value of character number i in x;
now result is result bignum+ tmp;
increment i;
decide on result;
To decide what text is (n - list of number) in bignum notation:
if n is BIGNUM_ZERO, decide on "0";
let prefix be "";
if entry 1 of n is -1:
now entry 1 of n is 1;
now prefix is "-";
let digits be "";
while n is not BIGNUM_ZERO:
let q be n bignum/ BIGNUM_1e9;
let r be n bignum- (q bignum* BIGNUM_1e9);
let s64 be r bignum+ BIGNUM_1e9;
let s1 be s64 converted from bignum;
let ss be the suffix of "[s1]" from 2;
now digits is "[ss][digits]";
now n is q;
let j be 1;
while character number j in digits is "0":
increment j;
decide on "[prefix][the suffix of digits from j]";
BIGNUM_2024 is always {1, 2024};
Section - Text Numbers
To decide what list of numbers is the digits of (N - text):
let digits be a list of numbers;
repeat with i running from 1 to the number of characters in N:
add the digit value of character number i in N to digits;
decide on digits.
Section - Lists of numbers
To decide if (items - list of numbers) is monotonically increasing:
let length be the number of entries in items;
repeat with i running from 1 to length - 1:
let x be entry i of items;
let y be entry i + 1 of items;
if y < x, decide no;
decide yes;
To decide if (items - list of numbers) is monotonically decreasing:
let length be the number of entries in items;
repeat with i running from 1 to length - 1:
let x be entry i of items;
let y be entry i + 1 of items;
if y > x, decide no;
decide yes;
To decide which list of numbers is (items - list of numbers) sorted by (cmp - phrase (number, number) -> truth state):
if the number of entries in items <= 1, decide on items;
let pivot be entry 1 of items;
let left be a list of numbers;
let right be a list of numbers;
repeat with i running from 2 to the number of entries in items:
let item be entry i of items;
if cmp applied to item and pivot is true:
add item to left;
otherwise:
add item to right;
now left is left sorted by cmp;
now right is right sorted by cmp;
add pivot to left;
add right to left;
decide on left;
To decide which list of list of numbers is (items - list of list of numbers) sorted by (cmp - phrase (list of number, list of number) -> truth state):
if the number of entries in items <= 1, decide on items;
let pivot be entry 1 of items;
let left be a list of list of numbers;
let right be a list of list of numbers;
repeat with i running from 2 to the number of entries in items:
let item be entry i of items;
if cmp applied to item and pivot is true:
add item to left;
otherwise:
add item to right;
now left is left sorted by cmp;
now right is right sorted by cmp;
add pivot to left;
add right to left;
decide on left;
To sort (items - list of values of kind K) by (cmp - phrase (K, K) -> number):
(- LIST_OF_TY_Sort2({-lvalue-by-reference:items}, 1, {cmp}-->1) -).
Include (-
Global LIST_OF_TY_Sort_cf2;
[ LIST_OF_TY_Sort2 list dir cf i j no_items v;
BlkMakeMutable(list);
no_items = BlkValueRead(list, LIST_LENGTH_F);
SetSortDomain(ListSwapEntries, ListCompareEntries2);
LIST_OF_TY_Sort_cf = cf;
SortArray(list, 0, dir, no_items, 0);
];
[ ListCompareEntries2 list col i j d cf;
if (i==j) return 0;
i = BlkValueRead(list, LIST_ITEM_BASE+i-1);
j = BlkValueRead(list, LIST_ITEM_BASE+j-1);
return LIST_OF_TY_Sort_cf(i, j);
];
-)
Section - Binary Heaps
To decide which number is the binary heap parent of (x - number):
decide on ((x - 2) / 2) + 1;
To decide which number is the binary heap left child of (x - number):
decide on x * 2;
To decide which number is the binary heap right child of (x - number):
decide on (x * 2) + 1;
Section - Grids
To decide which number is the manhattan distance from (ax - number) and (ay - number) to (bx - number) and (by - number):
let dx be the integer absolute value of (ax - bx);
let dy be the integer absolute value of (ay - by);
decide on dx + dy;
Section - Lists
To swap entry (i - number) and (j - number) in (items - list of values of kind K):
(- ListSwapEntries({-lvalue-by-reference:items}, {i}, {j}, 0); -);
To decide which K is the last entry of (items - list of values of kind K):
let n be the number of entries in items;
decide on entry n of items;
To decide which (list of Ks) is the last (k - number) entries of (items - list of values of kind K):
let result be a list of Ks;
let n be the number of entries in items;
repeat with i running from n - k + 1 to n:
add entry i of items to result;
decide on result;
To decide which number is the index of (v - value of kind K) in (items - list of Ks):
let n be the number of entries in items;
repeat with i running from 1 to n:
if entry i in items is v:
decide on i;
decide on 0;
[The following override seems to improve the performance of list insertion, though my benchmarking has not been rigorous.]
Include (-
[ LIST_OF_TY_InsertItem list v posnflag posn nodups i no_items ex nv contents_kind;
if ((list==0) || (BlkValueWeakKind(list) ~= LIST_OF_TY)) return false;
if (nodups && (LIST_OF_TY_FindItem(list, v))) return list;
no_items = BlkValueRead(list, LIST_LENGTH_F);
BlkValueWrite(list, LIST_LENGTH_F, no_items); ! Forces the list to be mutable
contents_kind = BlkValueRead(list, LIST_ITEM_KOV_F);
if ((posnflag) && ((posn<1) || (posn > no_items+1))) {
print "*** Couldn't add at entry ", posn, " in the list ";
LIST_OF_TY_Say(list, true);
print ", which has entries in the range 1 to ", no_items, " ***^";
RunTimeProblem(RTP_LISTRANGEERROR);
rfalse;
}
ex = BlkValueLBCapacity(list);
if (no_items+LIST_ITEM_BASE+1 > ex) {
ex = no_items+LIST_ITEM_BASE+1;
ex = (ex+(ex>>1)+7)&~7;
if (BlkValueSetLBCapacity(list, ex) == false) return 0;
}
if (KOVIsBlockValue(contents_kind)) {
nv = BlkValueCreate(contents_kind);
BlkValueCopy(nv, v);
v = nv;
}
if (posnflag) {
posn--;
for ( i=no_items:i>posn:i-- ) {
BlkValueWrite(list, i+LIST_ITEM_BASE,
BlkValueRead(list, i-1+LIST_ITEM_BASE));
}
BlkValueWrite(list, posn+LIST_ITEM_BASE, v);
} else {
BlkValueWrite(list, no_items+LIST_ITEM_BASE, v);
}
BlkValueWrite(list, LIST_LENGTH_F, no_items+1);
return list;
];
-) replacing "LIST_OF_TY_InsertItem".
Section - Binary Search
To decide which number is the lower bound index of (target - value of kind K) in (items - list of Ks):
let length be the number of entries in items;
let low be 0;
while length > 0:
let half length be length / 2;
let mid be low + half length;
if entry (mid + 1) in items < target:
now low is mid + 1;
now length is length - (half length + 1);
otherwise:
now length is half length;
decide on (low + 1).
To decide whether (target - value of kind K) is in already-sorted (items - list of Ks):
let i be the lower bound index of target in items;
let length be the number of entries in items;
if i <= length and entry i in items is target:
decide yes;
decide no;
To decide whether (target - value of kind K) is not in already-sorted (items - list of Ks):
if target is in already-sorted items, decide no;
decide yes;
To decide which (list of Ks) is the distinct items of already-sorted (items - list of values of kind K):
let result be a list of Ks;
let n be the number of entries in items;
if n < 1, decide on result;
add entry 1 of items to result;
repeat with i running from 2 to n:
let current be entry i of items;
if current is not previous:
add current to result;
now previous is current;
decide on result;
To decide which number is the distinct count of already-sorted (items - list of values of kind K):
let result be 0;
let n be the number of entries in items;
if n < 1, decide on result;
let previous be entry 1 of items;
increment result;
repeat with i running from 2 to n:
let current be entry i of items;
if current is not previous:
increment result;
now previous is current;
decide on result;
To decide which number is the sorted count of (target - value of kind K) in (items - list of Ks):
let i be the lower bound index of target in items;
let length be the number of entries in items;
let count be 0;
while i <= length and entry i in items is target:
increment i;
increment count;
decide on count;
Section - Merging sorted lists
To decide which list of Ks is the merge of already-sorted (x - list of values of kind K) and (y - list of Ks):
let result be a list of Ks;
let i be 1;
let j be 1;
let xn be the number of entries in x;
let yn be the number of entries in y;
while i <= xn and j <= yn:
if entry i in x < entry j in y:
add entry i in x to result;
increment i;
else:
add entry j in y to result;
increment j;
while i <= xn:
add entry i in x to result;
increment i;
while j <= yn:
add entry j in y to result;
increment j;
decide on result;
To decide which list of Ks is the unique merge of already-sorted (x - list of values of kind K) and (y - list of Ks):
let result be a list of Ks;
let i be 1;
let j be 1;
let n be 0;
let xn be the number of entries in x;
let yn be the number of entries in y;
while i <= xn and j <= yn:
if entry i in x < entry j in y:
if n is 0 or entry i in x is not entry n in result:
add entry i in x to result;
increment n;
increment i;
else:
if n is 0 or entry j in y is not entry n in result:
add entry j in y to result;
increment n;
increment j;
while i <= xn:
if n is 0 or entry i in x is not entry n in result:
add entry i in x to result;
increment n;
increment i;
while j <= yn:
if n is 0 or entry j in y is not entry n in result:
add entry j in y to result;
increment n;
increment j;
decide on result;
To decide which list of Ks is the intersection of already-sorted (x - list of values of kind K) and (y - list of Ks):
let result be a list of Ks;
let i be 1;
let j be 1;
let xn be the number of entries in x;
let yn be the number of entries in y;
while i <= xn and j <= yn:
if (entry i in x) < (entry j in y):
increment i;
else if (entry i in x) > (entry j in y):
increment j;
else:
add entry i in x to result;
increment i;
increment j;
decide on result;
Section - Blank Lines
Entering a blank line is an action applying to nothing.
Rule for printing a parser error when the latest parser error is the I beg your pardon error:
try entering a blank line instead.
Section - Punctuation Stripping
Punctuation stripping enabled is a truth state that varies.
After reading a command:
if punctuation stripping enabled is true:
let T be "[the player's command]";
replace the regular expression "<,|:>" in T with " ";
change the text of the player's command to T;
To enable punctuation stripping:
now punctuation stripping enabled is true.
To disable punctuation stripping:
now punctuation stripping enabled is false.
Section - Raw Input
Raw input enabled is a truth state that varies.
Before reading a command:
while raw input enabled is true:
try reading a raw input;
To enable raw input:
now raw input enabled is true;
To disable raw input:
now raw input enabled is false;
Reading a raw input is an action applying to nothing.
Carry out reading a raw input:
read raw input;
To read raw input:
(- PrintPrompt(); DrawStatusLine(); GetLongInput(); -).
To decide what text is the/-- raw input:
(- DecideLongInput({-new:text}) -).
To decide what number is digit (i - number) in the/-- raw input:
(- DecideDigitInLongInput({i}) -).
To decide what number is the/-- raw input size:
(- DecideLongInputSize() -).
Include (-
Constant LONG_BUFFER_LEN = 30000;
Array long_buffer buffer LONG_BUFFER_LEN;
[ GetLongInput done;
done = false;
glk_request_line_event(gg_mainwin,long_buffer+WORDSIZE,LONG_BUFFER_LEN-WORDSIZE,0);
while (~~done) {
glk_select(gg_event);
switch (gg_event-->0) {
5: ! evtype_Arrange
DrawStatusLine();
3: ! evtype_LineInput
if (gg_event-->1 == gg_mainwin) {
long_buffer-->0 = gg_event-->2;
done = true;
}
}
}
];
[ DecideLongInput txt;
TEXT_CopyFromByteArray(txt,long_buffer+WORDSIZE,long_buffer-->0);
return txt;
];
! Taken from Unified Glulx Input
[ TEXT_CopyFromByteArray txt buf len ubuf ix;
TEXT_TY_Transmute(txt);
ubuf = VM_AllocateMemory((len+1)*WORDSIZE);
for (ix=0 : ix<len : ix++) {
ubuf-->ix = buf->ix;
}
ubuf-->len = 0;
BlkValueMassCopyFromArray(txt,ubuf,4,len+1);
VM_FreeMemory(ubuf);
];
[ DecideDigitInLongInput i;
if ((i<=0) || (i>long_buffer-->0)) return -1;
switch ((long_buffer+WORDSIZE)->(i-1)) {
'0': return 0;
'1': return 1;
'2': return 2;
'3': return 3;
'4': return 4;
'5': return 5;
'6': return 6;
'7': return 7;
'8': return 8;
'9': return 9;
}
return -2;
];
[ DecideLongInputSize;
return long_buffer-->0;
]
-)
Section - Output Control
To flush output:
(- FlushOutput(); -).
Include (-
[ FlushOutput;
glk_request_timer_events(1);
while (1) {
glk_select(gg_event);
if (gg_event-->0 == evtype_Timer) {
glk_request_timer_events(0);
break;
}
}
];
-)
Section - Debugging
The debug level is a number that varies.
ERROR is always 0.
WARNING is always 1.
INFO is always 2.
Log flushing is a truth state that varies.
Log flushing is true.
To log (msg - text) at (level - number):
if level <= debug level:
say "[msg][line break]";
if log flushing is true:
flush output;
To log (msg - text) at (level - number) every (n - number) of (i - number):
if level <= debug level and i is divisible by n:
say "[msg][line break]";
if log flushing is true:
flush output;
To set log level (level - number):
now debug level is level;