From 358249e78a0c4ccd8bdfc8894720ba63a18d26be Mon Sep 17 00:00:00 2001 From: Alan R Evans Date: Mon, 1 Dec 2025 14:04:11 +0000 Subject: [PATCH] day1 --- 2025/go/.vscode/launch.json | 16 + 2025/go/day01/day01.go | 128 + 2025/go/day01/day01_test.go | 34 + 2025/go/day01/input.txt | 4777 ++++++++++++++++++++++++ 2025/go/go.mod | 16 + 2025/go/go.sum | 11 + 2025/go/main.go | 154 + 2025/go/utils/dijkstra/graph.go | 241 ++ 2025/go/utils/dijkstra/object.go | 35 + 2025/go/utils/dijkstra/queue.go | 65 + 2025/go/utils/grid2d/grid2d.go | 77 + 2025/go/utils/inputFile.go | 63 + 2025/go/utils/inputs/inputs.go | 56 + 2025/go/utils/memo/memo.go | 47 + 2025/go/utils/ringbuffer/ringbuffer.go | 56 + 2025/go/utils/sparseGrid/sparseGrid.go | 81 + 2025/go/utils/utils.go | 222 ++ 17 files changed, 6079 insertions(+) create mode 100644 2025/go/.vscode/launch.json create mode 100644 2025/go/day01/day01.go create mode 100644 2025/go/day01/day01_test.go create mode 100644 2025/go/day01/input.txt create mode 100644 2025/go/go.mod create mode 100644 2025/go/go.sum create mode 100644 2025/go/main.go create mode 100644 2025/go/utils/dijkstra/graph.go create mode 100644 2025/go/utils/dijkstra/object.go create mode 100644 2025/go/utils/dijkstra/queue.go create mode 100644 2025/go/utils/grid2d/grid2d.go create mode 100644 2025/go/utils/inputFile.go create mode 100644 2025/go/utils/inputs/inputs.go create mode 100644 2025/go/utils/memo/memo.go create mode 100644 2025/go/utils/ringbuffer/ringbuffer.go create mode 100644 2025/go/utils/sparseGrid/sparseGrid.go create mode 100644 2025/go/utils/utils.go diff --git a/2025/go/.vscode/launch.json b/2025/go/.vscode/launch.json new file mode 100644 index 0000000..24391a3 --- /dev/null +++ b/2025/go/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Package", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${fileDirname}", + "args": ["1"] + } + ] +} \ No newline at end of file diff --git a/2025/go/day01/day01.go b/2025/go/day01/day01.go new file mode 100644 index 0000000..ec678aa --- /dev/null +++ b/2025/go/day01/day01.go @@ -0,0 +1,128 @@ +package day01 + +import ( + "adventofcode2025/utils" + "fmt" + "strings" +) + +type Dir int + +const ( + Left Dir = iota + Right + Safe + Unsafe +) + +type Instruction struct { + Turn Dir + Steps int +} + +func Part1(input string) int { + lines := strings.Split(input, "\n") + position := 50 + code := 0 + Instructions := make([]Instruction, 0) + for _, line := range lines { + var steps int + var dir Dir + switch line[0] { + case 'L': + steps = utils.MustAtoi(line[1:]) + dir = Left + case 'R': + steps = utils.MustAtoi(line[1:]) + dir = Right + default: + fmt.Println("Invalid direction") + continue + } + if steps > 100 { + steps = steps % 100 + } + Instructions = append(Instructions, Instruction{Turn: dir, Steps: steps}) + } + fmt.Print(Instructions) + for _, instr := range Instructions { + if instr.Turn == Left { + if position-instr.Steps < 0 { + position = 100 + (position - instr.Steps) + } else { + position -= instr.Steps + } + } else if instr.Turn == Right { + if position+instr.Steps >= 100 { + position = (position + instr.Steps) - 100 + } else { + position += instr.Steps + } + } + fmt.Println("\n", instr.Turn, instr.Steps, "->", position) + if position == 0 { + code++ + } + } + return code +} + +func Part2(input string) int { + lines := strings.Split(input, "\n") + position := 50 + code := 0 + Instructions := make([]Instruction, 0) + for _, line := range lines { + var steps int + var dir Dir + switch line[0] { + case 'L': + steps = utils.MustAtoi(line[1:]) + dir = Left + case 'R': + steps = utils.MustAtoi(line[1:]) + dir = Right + default: + fmt.Println("Invalid direction") + continue + } + Instructions = append(Instructions, Instruction{Turn: dir, Steps: steps}) + } + fmt.Print(Instructions) + for _, instr := range Instructions { + if instr.Steps > 100 { + code = code + (instr.Steps / 100) + instr.Steps = instr.Steps % 100 + } + if instr.Turn == Left { + if position-instr.Steps < 0 { + if position != 0 { + code++ + } + position = 100 + (position - instr.Steps) + + } else { + position -= instr.Steps + if position == 0 { + code++ + } + } + } else if instr.Turn == Right { + if position+instr.Steps > 99 { + if position != 0 { + code++ + } + position = (position + instr.Steps) - 100 + } else { + position += instr.Steps + if position == 0 { + code++ + } + } + } + + fmt.Println("\n", instr.Turn, instr.Steps, "->", position, "code:", code) + + } + return code +} diff --git a/2025/go/day01/day01_test.go b/2025/go/day01/day01_test.go new file mode 100644 index 0000000..788fbbe --- /dev/null +++ b/2025/go/day01/day01_test.go @@ -0,0 +1,34 @@ +package day01 + +import ( + "testing" + + "github.com/stretchr/testify/require") + +func TestPart1(t *testing.T) { + r := Part1(`L68 +L30 +R48 +L5 +R60 +L55 +L1 +L99 +R14 +L82`) + require.Equal(t, 3, r) +} + +func TestPart2(t *testing.T) { + r := Part2(`L68 +L30 +R48 +L5 +R60 +L55 +L1 +L99 +R14 +L82`) + require.Equal(t, 6, r) +} diff --git a/2025/go/day01/input.txt b/2025/go/day01/input.txt new file mode 100644 index 0000000..674649c --- /dev/null +++ b/2025/go/day01/input.txt @@ -0,0 +1,4777 @@ +R46 +L11 +R26 +L29 +R14 +L26 +R18 +L38 +L48 +R45 +L8 +L48 +L2 +R34 +R4 +R8 +R35 +R41 +L16 +R31 +L36 +R16 +L22 +L35 +L33 +R42 +R42 +L43 +R28 +L31 +L38 +L47 +L29 +L13 +R13 +L17 +R16 +L20 +L16 +R18 +L21 +R41 +R37 +L10 +R48 +L44 +R26 +R17 +R7 +R78 +L90 +L33 +L91 +R74 +L56 +L53 +L90 +R97 +R42 +R30 +R17 +L47 +R4 +L4 +L23 +R23 +L66 +L45 +L82 +L23 +R90 +R70 +L29 +L66 +R51 +L54 +R54 +R32 +L48 +L95 +L57 +R63 +L14 +R86 +L67 +L45 +L39 +L35 +R19 +R19 +R45 +R87 +R89 +L83 +L57 +R22 +L22 +L36 +L53 +L95 +L616 +L87 +L13 +R67 +R933 +L70 +R75 +R74 +L16 +R20 +R17 +R45 +L92 +L64 +L61 +L28 +R541 +L42 +R1 +R27 +L77 +R850 +R39 +L39 +L373 +R66 +R53 +R16 +L28 +R66 +L7 +L68 +R355 +L80 +R52 +R48 +L16 +R13 +R78 +R330 +R995 +R57 +R643 +R31 +L26 +L1 +R96 +L93 +L48 +L59 +R27 +R83 +R89 +L99 +L719 +L83 +L3 +R83 +L78 +R59 +L417 +R48 +L40 +R78 +R83 +R89 +R26 +L98 +L75 +R72 +R68 +R184 +L77 +R12 +L12 +L38 +R13 +R69 +R56 +R95 +R5 +R26 +L26 +L76 +R90 +L927 +R13 +L96 +L40 +R85 +L449 +L23 +R23 +L160 +R98 +R4 +R52 +L394 +R9 +L44 +L65 +L80 +L20 +L24 +L76 +L26 +L74 +R50 +L50 +L305 +R5 +L6 +R49 +L667 +R724 +L89 +R864 +L97 +R43 +R77 +L251 +R53 +L125 +L32 +L643 +R85 +L85 +L710 +R510 +L93 +R90 +R81 +R48 +R647 +L473 +R40 +R76 +R20 +L36 +R97 +L90 +R93 +R55 +L79 +L91 +L352 +L166 +L49 +R757 +L11 +R36 +R4 +L790 +R86 +L88 +R31 +L43 +R34 +R575 +R64 +L73 +L352 +R57 +L753 +R48 +L22 +R97 +L975 +R11 +R73 +R97 +R19 +R417 +L13 +R696 +L26 +L74 +R88 +R154 +L42 +L79 +L578 +R95 +R62 +R751 +L563 +R61 +R83 +R73 +L623 +R18 +L44 +L56 +R58 +L37 +L28 +L60 +L30 +R97 +R83 +L65 +R90 +L92 +L16 +L40 +L336 +R94 +L18 +L329 +R69 +R60 +R56 +R91 +R40 +L87 +L96 +R63 +R33 +R51 +L66 +L85 +R76 +R27 +L77 +L233 +L568 +L25 +L856 +R656 +L4 +R13 +L376 +L29 +L32 +R928 +R62 +L179 +L83 +R24 +L24 +R120 +L20 +R10 +R90 +L62 +R51 +R77 +L18 +L465 +L75 +L30 +R22 +L969 +R15 +R212 +L823 +L83 +R48 +L54 +R99 +R64 +R91 +R13 +L50 +L63 +R796 +L89 +L91 +L16 +R17 +R83 +R91 +L91 +L394 +L84 +R68 +R26 +L16 +R9 +R91 +R73 +L4 +L4 +R91 +L95 +L881 +L80 +L30 +L65 +R64 +L59 +R978 +R12 +L46 +R546 +L4 +L72 +R76 +R889 +L64 +L80 +R90 +R65 +L25 +R25 +R12 +R922 +R69 +R96 +R734 +L81 +R67 +R22 +L21 +R546 +L514 +L52 +R50 +L73 +R503 +L99 +R85 +L588 +L61 +R83 +R750 +R50 +L17 +L47 +L36 +R941 +R59 +L86 +R450 +L64 +L40 +L405 +R845 +L39 +L61 +R19 +R8 +R73 +L544 +R237 +R23 +L17 +L11 +L58 +R70 +R46 +R42 +R12 +R608 +L40 +L74 +R106 +R66 +R34 +L20 +L80 +R62 +R38 +R27 +R73 +L174 +L79 +R59 +L607 +L735 +L95 +L413 +L56 +R37 +R910 +R98 +R55 +L58 +R90 +L30 +R298 +L21 +R837 +R84 +L306 +R6 +L91 +R91 +R93 +L9 +L84 +L73 +L13 +R86 +R72 +R801 +L59 +L81 +R693 +L26 +R72 +R861 +L26 +L25 +L121 +L65 +R1 +L14 +L10 +R356 +R8 +R4 +R25 +L66 +R92 +R8 +L49 +L99 +R63 +L12 +L203 +L53 +L24 +R166 +R44 +R315 +R481 +R42 +L403 +L20 +R52 +L65 +L35 +L64 +L235 +L663 +L30 +L20 +R11 +L41 +L58 +R223 +R22 +L645 +L735 +R35 +L80 +R63 +L83 +R61 +R90 +R49 +L123 +L95 +R18 +R18 +R91 +L99 +L10 +L75 +L81 +R756 +R301 +L513 +L9 +L34 +R227 +L33 +L65 +L661 +R94 +R27 +L34 +R574 +R79 +R47 +L22 +L986 +L992 +L81 +L85 +L669 +R23 +L843 +R55 +L456 +L82 +R12 +L65 +L109 +L22 +L82 +L71 +L683 +R21 +R37 +R35 +L38 +R90 +R13 +L172 +R80 +R292 +L70 +L30 +R56 +L756 +L5 +R827 +R30 +L97 +L55 +L288 +L21 +R51 +R12 +L54 +R11 +L11 +R70 +L70 +L78 +R90 +L12 +R892 +R8 +L50 +L850 +L83 +R83 +R33 +R11 +L28 +R39 +L204 +R642 +L993 +R1 +R799 +L47 +R54 +L58 +L90 +L59 +L154 +L35 +R14 +L58 +L67 +R84 +R16 +R71 +L371 +R80 +L80 +R98 +L70 +L76 +R48 +R55 +R75 +L30 +R88 +L83 +R66 +L71 +R13 +R25 +R8 +R54 +L10 +L7 +L837 +L38 +R92 +L49 +L51 +R66 +R334 +L802 +R14 +R88 +L560 +L62 +L478 +L3 +L83 +L18 +L96 +R473 +L39 +L27 +L7 +R31 +R69 +L564 +L66 +L95 +L27 +L748 +L26 +R220 +L52 +R758 +R18 +R24 +L11 +L31 +L45 +L26 +L81 +L70 +L21 +R28 +L24 +R47 +R92 +R73 +R221 +R6 +R78 +L45 +R58 +R309 +L314 +R56 +R794 +L74 +L381 +R83 +L48 +L5 +L482 +L4 +R658 +L83 +R814 +R586 +L4 +L90 +R48 +L54 +R71 +L23 +L10 +R62 +R34 +R59 +L93 +R75 +R25 +L19 +L27 +R26 +L79 +R999 +R54 +R43 +R3 +R4 +R252 +R144 +L53 +L86 +R38 +L99 +R20 +L49 +L509 +R38 +L99 +L601 +R60 +L721 +R78 +L17 +L22 +L78 +L352 +R24 +L72 +R419 +R81 +L97 +R92 +L95 +R51 +L51 +R32 +L344 +R12 +L70 +L11 +L49 +L70 +R73 +R66 +R648 +R85 +R532 +R109 +R86 +L86 +R56 +L283 +R40 +R74 +R97 +R17 +R845 +L59 +L38 +L22 +L4 +R94 +L30 +R36 +R77 +L61 +R45 +L30 +R433 +L10 +R30 +R80 +R95 +R129 +R89 +L62 +L42 +L41 +L90 +L705 +R97 +R430 +L952 +L999 +R851 +L62 +L71 +R333 +R5 +L20 +L85 +R444 +R890 +L81 +L53 +L261 +L329 +R6 +R84 +L901 +L99 +R28 +L10 +R554 +R42 +R71 +R215 +R571 +R744 +R413 +L228 +R297 +L811 +L186 +R277 +L65 +R922 +L95 +R39 +L80 +R2 +L877 +R77 +L25 +L102 +R94 +R874 +L601 +R69 +L79 +L88 +L342 +R78 +R32 +R15 +L25 +L61 +R15 +L83 +R5 +L770 +L88 +R82 +R5 +L5 +R44 +R56 +L6 +R406 +R83 +L83 +L93 +L7 +L234 +L13 +L68 +L85 +L2 +L679 +R81 +R96 +L887 +R44 +R93 +R48 +R6 +L14 +L81 +L78 +R73 +R54 +R846 +L1 +L15 +R5 +R17 +R94 +L50 +R76 +R238 +R36 +L80 +R908 +L44 +L68 +R219 +L67 +L36 +L45 +R38 +R75 +R49 +R751 +R44 +R93 +R44 +L37 +L76 +R58 +L22 +R53 +R43 +L23 +L3 +R276 +L1 +R13 +R127 +L52 +L37 +L24 +L874 +R98 +R54 +L7 +R53 +R45 +R555 +R92 +R8 +L38 +R52 +R986 +L179 +L21 +L6 +R6 +L37 +L663 +R77 +L32 +L43 +L2 +R45 +L45 +R90 +L90 +L52 +R52 +R69 +L31 +R325 +L354 +R291 +R819 +R22 +L41 +R26 +R11 +L32 +R795 +L45 +L55 +L726 +L67 +R65 +R66 +R21 +R41 +L56 +L27 +R50 +L74 +L93 +L55 +R3 +L64 +R16 +R64 +L39 +L76 +R451 +L4 +R62 +R942 +L54 +R91 +L37 +L8 +L32 +L32 +L28 +R43 +R57 +L64 +R513 +R74 +R77 +R63 +L924 +R70 +R25 +L34 +R375 +L13 +R30 +R32 +L27 +R3 +L20 +L80 +R320 +L20 +R987 +R78 +R35 +L56 +R56 +R37 +L537 +R25 +R75 +R41 +R39 +R2 +L22 +R57 +L55 +L52 +R15 +L25 +L35 +L26 +L39 +L54 +L516 +R81 +L11 +R56 +R44 +L43 +L53 +R644 +L48 +L62 +R81 +L7 +R75 +R32 +L997 +L49 +L43 +L30 +L71 +L67 +L52 +R27 +L437 +R943 +R884 +R97 +L824 +L50 +L50 +L1 +R8 +L7 +L45 +L62 +R9 +L61 +R73 +R97 +L79 +L32 +R21 +L69 +R48 +R39 +R93 +L32 +L688 +L12 +L716 +R52 +L36 +R42 +R8 +L31 +R66 +R89 +R26 +R70 +R30 +R4 +R96 +L89 +R89 +R16 +R84 +R25 +R92 +L432 +L510 +L75 +R528 +R51 +R738 +L82 +L68 +L767 +L99 +R52 +R501 +R946 +R93 +L90 +R97 +L51 +R61 +R61 +R509 +R320 +R77 +R80 +L57 +L65 +R65 +R193 +R78 +R54 +L46 +R5 +R16 +R7 +R28 +L24 +R89 +R8 +R50 +L71 +R13 +L71 +L12 +L80 +R763 +R62 +R502 +L99 +L93 +L85 +R13 +R49 +L39 +L31 +L67 +R84 +L72 +L24 +R94 +R6 +L73 +R73 +R47 +R25 +R11 +R549 +R907 +R46 +L85 +L62 +R67 +R95 +L926 +L74 +L3 +L80 +L10 +R24 +R311 +R547 +R18 +L7 +L869 +R80 +R89 +R27 +L186 +R59 +L14 +L86 +L20 +R21 +L89 +R196 +L56 +L559 +R14 +L33 +R37 +L313 +R2 +R25 +R24 +L49 +L75 +L67 +L520 +R762 +L685 +R38 +L35 +L45 +R622 +R55 +L50 +L99 +R8 +L83 +L26 +L72 +R67 +L47 +R52 +L38 +L45 +L11 +R96 +R298 +R88 +L99 +L89 +L360 +L27 +R87 +L276 +R76 +L54 +R77 +R77 +L51 +R66 +R668 +L127 +L56 +R60 +R58 +R82 +R757 +L57 +L55 +R21 +L64 +L2 +L35 +R839 +R96 +R27 +R61 +L70 +R812 +L49 +R12 +L493 +R5 +L5 +L34 +L66 +R819 +L19 +L10 +R73 +R72 +L48 +R339 +L26 +R73 +L52 +L72 +L759 +R10 +L54 +L492 +L97 +L65 +R8 +L51 +R51 +R1 +L42 +R95 +L85 +R20 +L89 +L234 +L21 +L18 +L270 +L17 +L40 +R90 +L23 +R87 +L850 +R210 +R95 +R91 +L88 +R88 +R10 +R190 +L38 +L85 +R23 +R38 +R2 +L740 +L40 +L168 +R92 +L84 +L16 +R423 +L68 +R61 +R709 +R43 +R56 +L26 +R688 +R49 +R81 +L29 +L271 +L29 +R65 +L41 +L24 +L54 +L17 +L712 +R98 +R27 +L50 +L63 +R80 +R720 +L40 +R86 +R54 +L69 +R69 +R79 +R221 +R92 +L415 +L68 +R89 +R2 +R61 +R90 +R49 +R37 +R10 +L54 +R44 +R96 +R8 +L93 +R60 +L34 +R47 +R30 +L38 +R35 +R252 +R507 +L198 +R2 +L15 +L96 +R24 +L76 +L582 +L966 +R78 +R11 +R96 +R47 +R18 +L3 +R29 +R27 +R83 +R214 +L93 +L7 +L89 +L11 +R31 +R69 +L569 +R73 +R96 +L43 +R143 +R34 +R99 +R68 +R17 +L71 +R453 +L232 +L575 +L13 +R3 +L245 +L38 +L46 +L16 +R662 +L42 +L22 +L28 +R92 +R41 +R22 +L23 +R60 +L75 +L90 +L5 +L98 +R48 +L80 +L58 +R51 +L793 +L44 +R95 +L53 +R2 +L70 +R69 +L40 +R13 +R91 +L69 +R27 +R79 +L14 +L398 +R444 +R63 +L155 +L39 +L73 +R72 +L984 +R10 +R187 +L65 +R976 +R76 +L82 +L3 +R85 +L19 +L31 +R55 +R40 +R6 +L751 +R9 +R91 +R57 +L57 +R96 +R50 +R768 +R59 +L377 +R78 +L74 +L69 +L88 +L944 +R55 +L315 +L988 +R743 +R86 +R351 +R69 +L48 +L98 +R46 +L8 +L648 +L44 +L87 +L13 +L4 +R9 +R77 +L49 +L74 +R41 +L96 +L181 +R853 +R24 +L30 +L75 +L452 +R57 +L43 +R43 +R246 +R41 +R836 +R977 +R65 +R49 +R86 +R80 +L80 +L55 +L81 +R36 +R337 +R63 +R287 +L87 +L20 +R18 +R2 +R39 +L38 +L34 +R74 +L10 +L231 +R25 +R75 +R10 +R90 +R67 +L67 +R15 +L90 +L25 +R62 +L68 +R6 +R94 +L94 +R794 +L45 +R51 +L69 +L984 +L686 +L61 +R454 +R73 +R22 +R58 +L1 +R94 +L47 +R47 +R48 +R152 +R41 +L62 +R88 +L67 +R61 +L77 +R16 +L61 +L75 +R97 +R39 +L59 +L70 +R29 +L84 +R86 +R34 +R69 +R95 +R8 +R52 +R50 +R90 +R12 +L12 +L34 +R234 +R46 +L346 +L98 +R98 +R606 +L764 +R16 +R42 +R26 +L61 +R24 +R3 +R93 +L85 +R730 +R493 +R53 +L56 +L78 +L27 +L180 +L944 +R109 +L83 +R83 +R99 +L322 +R38 +L15 +R246 +L178 +L62 +R94 +R81 +R767 +L307 +R59 +L742 +R24 +R18 +R44 +L822 +L222 +L37 +R772 +R53 +L25 +R37 +R342 +R13 +L55 +R95 +R83 +L24 +L54 +L36 +L64 +R53 +R47 +R89 +L45 +L54 +L65 +R369 +R56 +R617 +R33 +L99 +R99 +R28 +L7 +L3 +R69 +R99 +R72 +R42 +L28 +R511 +L60 +R60 +L83 +R34 +R11 +R45 +L79 +L51 +L239 +L61 +R89 +R51 +L83 +R83 +L4 +L933 +L165 +R2 +R77 +R23 +L55 +L16 +L29 +L94 +L2 +L66 +L41 +R3 +R49 +L49 +L33 +R833 +R56 +R44 +L55 +R8 +R78 +L31 +L34 +R58 +R10 +R47 +L9 +L72 +R654 +L54 +L137 +L163 +R41 +L41 +R47 +R53 +R165 +L65 +L28 +R28 +L89 +R89 +R366 +L59 +L83 +L24 +L94 +R61 +R68 +L40 +R5 +R14 +R86 +R11 +R64 +R93 +L39 +L54 +L75 +R21 +R79 +L35 +R37 +R98 +L57 +L515 +L28 +R463 +R67 +R70 +R25 +R75 +L998 +R97 +L599 +L76 +L77 +L216 +R26 +R82 +R2 +L77 +L43 +R16 +L3 +L10 +R576 +L503 +R443 +L44 +L29 +L31 +R564 +L82 +R82 +L86 +R19 +L33 +R721 +L76 +L5 +L40 +L41 +L15 +L44 +L74 +R833 +L59 +R32 +L90 +L39 +R956 +R38 +R3 +L516 +L309 +R703 +R39 +L62 +L679 +L687 +L8 +R55 +R664 +R87 +R32 +L666 +L67 +R314 +L78 +R86 +L135 +L41 +R33 +L65 +R85 +L980 +R53 +R88 +R54 +R78 +R67 +R20 +L74 +L91 +L25 +L61 +L19 +L295 +L26 +R41 +R38 +R55 +L8 +L42 +L72 +R14 +R2 +R31 +L86 +R949 +L97 +R30 +L60 +L69 +R45 +L115 +R97 +L927 +L268 +R397 +R71 +R16 +R50 +L10 +L15 +R59 +L97 +R82 +L810 +R25 +R43 +L843 +L16 +R616 +L583 +R83 +R34 +R82 +R85 +L790 +R37 +R47 +L95 +L2 +L51 +R53 +R68 +R952 +R377 +L87 +R9 +R96 +R21 +L35 +R743 +R204 +L48 +R208 +L34 +R75 +L49 +R77 +R41 +R59 +L777 +R71 +L83 +R92 +L46 +L14 +L20 +R551 +L51 +L978 +R46 +R79 +R9 +R44 +L38 +R838 +R74 +L74 +L78 +L822 +R91 +R96 +R25 +R88 +L84 +R71 +R13 +L971 +L29 +L225 +R125 +L444 +L56 +R821 +R18 +R13 +L37 +R96 +L33 +R122 +L36 +L84 +R20 +L1 +L31 +R27 +L320 +L94 +R81 +R926 +R24 +L63 +L51 +L54 +R6 +L50 +R77 +L11 +L2 +L60 +R296 +L73 +L6 +R279 +R94 +R38 +R68 +R19 +R81 +R42 +R13 +L55 +L473 +R77 +R96 +L40 +L18 +R58 +R83 +R17 +R46 +R66 +R3 +R36 +L36 +L18 +L73 +R11 +R65 +R876 +R24 +L87 +L313 +L41 +L75 +R31 +L88 +L27 +L13 +R635 +L79 +L343 +R90 +R4 +L60 +L47 +R13 +L65 +L35 +R898 +L98 +L20 +L145 +L972 +R17 +R276 +L56 +R76 +R624 +L39 +R39 +R301 +R857 +R499 +R71 +L328 +L37 +R22 +L9 +R24 +L14 +R14 +L88 +R40 +L52 +R415 +R385 +L5 +L795 +R2 +R98 +L74 +L32 +R60 +L32 +R27 +R33 +L89 +R42 +R65 +L55 +L30 +L666 +L935 +R86 +L7 +R21 +R86 +R20 +R43 +R46 +L99 +L10 +R97 +L997 +R38 +R11 +L17 +L780 +R48 +L11 +L89 +L10 +L390 +R65 +L665 +R10 +R980 +R7 +L596 +L56 +L460 +R841 +R74 +R5 +R95 +L2 +R631 +L92 +L37 +R19 +L319 +R204 +L43 +L61 +L16 +R74 +L101 +L66 +L92 +L99 +R9 +L99 +R90 +R82 +R36 +R37 +L21 +L34 +R65 +R35 +L22 +R22 +R502 +L767 +L21 +R686 +R97 +R21 +L58 +L48 +L12 +L21 +L79 +R93 +L593 +R92 +L92 +L998 +L2 +L38 +R38 +L5 +R96 +L91 +L458 +L16 +L26 +L438 +L75 +R13 +L89 +R989 +R27 +R73 +R57 +L57 +L10 +R5 +R676 +L7 +R26 +R10 +L740 +L28 +L532 +L84 +L35 +R29 +R636 +L146 +L74 +L55 +L49 +R57 +R10 +L69 +R435 +L622 +L94 +L714 +R837 +L18 +R56 +L17 +R28 +R53 +R46 +L3 +L90 +R60 +R723 +L82 +L44 +L65 +R491 +L5 +L337 +L93 +R35 +R2 +L35 +L67 +R92 +R13 +L5 +R22 +L68 +L44 +R46 +L91 +R367 +R29 +R39 +L14 +R4 +L54 +R264 +R37 +R63 +L194 +L77 +L57 +R20 +R8 +R838 +R356 +L394 +L15 +L85 +L93 +L441 +R68 +R83 +L28 +L489 +L611 +R411 +L441 +L59 +L95 +R85 +L79 +R89 +L23 +L43 +L34 +R99 +L24 +L86 +R49 +R86 +R776 +R98 +R2 +L664 +L36 +R65 +R46 +R858 +L98 +L14 +R43 +L6 +R6 +R378 +R517 +L28 +R33 +L72 +R490 +R45 +L72 +L4 +R13 +R26 +L5 +R39 +L60 +R24 +R276 +L10 +R3 +L93 +R99 +L773 +L64 +L62 +L50 +R16 +L66 +R35 +L367 +L56 +L648 +L46 +R82 +L11 +L1 +L88 +L47 +L53 +L13 +L6 +R57 +L7 +R4 +L35 +R307 +R63 +L70 +R87 +L43 +L891 +L45 +L27 +L60 +R8 +R50 +L11 +R732 +L51 +L82 +R95 +L62 +R18 +L96 +R42 +L65 +R95 +R6 +R8 +R92 +L18 +R18 +R82 +L194 +L14 +R26 +L273 +R28 +L96 +R89 +L14 +R66 +R84 +L22 +R684 +R679 +R75 +L76 +L24 +R22 +L31 +L91 +L975 +L825 +R30 +R48 +L66 +L975 +L84 +L79 +L74 +R16 +R49 +L60 +L63 +R58 +R76 +L23 +R91 +R65 +R218 +R10 +R52 +R411 +L22 +L3 +R25 +L29 +R729 +R84 +R116 +L31 +L991 +R13 +L28 +R37 +L52 +R77 +R3 +R99 +R73 +L17 +R17 +L74 +R68 +L35 +R41 +R21 +L21 +L10 +L87 +L73 +L55 +L333 +L50 +L92 +L52 +R36 +R31 +R85 +R477 +L966 +R89 +L636 +L30 +R89 +R728 +L51 +L6 +R36 +R70 +L274 +L989 +L28 +R91 +L30 +R95 +R35 +R39 +L39 +R58 +R90 +L88 +R76 +L635 +R73 +L86 +R10 +L98 +L37 +L763 +R81 +R780 +R93 +R93 +R353 +R4 +L64 +R74 +L97 +R58 +L75 +L12 +L88 +R54 +R46 +R58 +L58 +R123 +R869 +R8 +R91 +L87 +R96 +R86 +L293 +R50 +R86 +L29 +R34 +L87 +L159 +L11 +R60 +R28 +R35 +R33 +R67 +L88 +L12 +L22 +L15 +L23 +L89 +L92 +L59 +R47 +L90 +L21 +L99 +L37 +R17 +R83 +L806 +R45 +R857 +L49 +R37 +L343 +R59 +L91 +L1 +R84 +L54 +R44 +R18 +L811 +L35 +L354 +L56 +L44 +L56 +L1 +L43 +R70 +L65 +R932 +L41 +L96 +L66 +R519 +R47 +R53 +L23 +R61 +R409 +R1 +L99 +R33 +L6 +L92 +R42 +R73 +R48 +L19 +L64 +L857 +R44 +L21 +L3 +R20 +L615 +R41 +L45 +R61 +R59 +R99 +L40 +L235 +R266 +R151 +R58 +R58 +R42 +R61 +L561 +L72 +R56 +R745 +L246 +L45 +L338 +R34 +L34 +R77 +R23 +L92 +R607 +L15 +R56 +R33 +R12 +L292 +L80 +L38 +L316 +R76 +L51 +R17 +R282 +R1 +R59 +L59 +R86 +R10 +R504 +L80 +L690 +R35 +R835 +L427 +R30 +R97 +R50 +L50 +R47 +L47 +R353 +R7 +R849 +L269 +R60 +R67 +R33 +R53 +L553 +R22 +L22 +L28 +R16 +L88 +L66 +L99 +R84 +R981 +L78 +L42 +R95 +R43 +R17 +L535 +L34 +R74 +L88 +L93 +L24 +R61 +R404 +R52 +L94 +R42 +R66 +L66 +L874 +L26 +L43 +R887 +L22 +R33 +R45 +L57 +L41 +R11 +L13 +R97 +L73 +R276 +L60 +L93 +R87 +L96 +R80 +L26 +R8 +R89 +L3 +L186 +R53 +R47 +R85 +R76 +L1 +L60 +R97 +L14 +R99 +R18 +L43 +L63 +R6 +L88 +R77 +R411 +R93 +R76 +R37 +L64 +R7 +L149 +R87 +R88 +R245 +L44 +R76 +R432 +L61 +L895 +R91 +L849 +L70 +R293 +R85 +R74 +R44 +R88 +R569 +L36 +R59 +L76 +R7 +R59 +L24 +R458 +R52 +R93 +R16 +L61 +R44 +L60 +L84 +L70 +R770 +L63 +R27 +R81 +R23 +R132 +L62 +L38 +R4 +L65 +L54 +R60 +R55 +R52 +R248 +L77 +R53 +R67 +L622 +R97 +R82 +R36 +L36 +R987 +L87 +L56 +R456 +L87 +R687 +L30 +R30 +R79 +R29 +L610 +R40 +L416 +L22 +L2 +R214 +L25 +R3 +L86 +L9 +L28 +L74 +L77 +R31 +R25 +R99 +R29 +R44 +L244 +R53 +R30 +L12 +L22 +L18 +L26 +L32 +L62 +R80 +L69 +R32 +L65 +R37 +R26 +L482 +R85 +L55 +L21 +R53 +L32 +R56 +R44 +L397 +R97 +L47 +L553 +L60 +R86 +R34 +R137 +L70 +L25 +R52 +L54 +L85 +R59 +L46 +L279 +R51 +L26 +L88 +R924 +L510 +L82 +R92 +L10 +L20 +R577 +L57 +R10 +R890 +L11 +L24 +R33 +R2 +L29 +L532 +R61 +R35 +L17 +L5 +L13 +L45 +R22 +R64 +R49 +L7 +L96 +R813 +L279 +R79 +R719 +L561 +L87 +L66 +L115 +R10 +L98 +L39 +R61 +L64 +R32 +L720 +R28 +L40 +R311 +R11 +L82 +R237 +R67 +L91 +L76 +R20 +R76 +L73 +L7 +R847 +L657 +R57 +R83 +L70 +R254 +R18 +L485 +L3 +R101 +L598 +R809 +L3 +L79 +L14 +L82 +R892 +R80 +R29 +R68 +R25 +R91 +L2 +L514 +R18 +L68 +R361 +L55 +R44 +R947 +L47 +L5 +L55 +R10 +R50 +R476 +L581 +R5 +L56 +R780 +L24 +R594 +L72 +L67 +R45 +L35 +L27 +R533 +L77 +L94 +L468 +L32 +R439 +L271 +L737 +R56 +L44 +R594 +L42 +R5 +R66 +R34 +R30 +R33 +L42 +L21 +R79 +R63 +R58 +L32 +L912 +L78 +R822 +R6 +R41 +L74 +L73 +R28 +L14 +R86 +L41 +R9 +R9 +L409 +R40 +R59 +L94 +R627 +R392 +R23 +L595 +L517 +R761 +L764 +R75 +R825 +R284 +R739 +R76 +R444 +R712 +L5 +L48 +R98 +L18 +L34 +R52 +L37 +L93 +L670 +R58 +R80 +L34 +L1 +L3 +L81 +R81 +L51 +R83 +R668 +L33 +L97 +R30 +R3 +L20 +L53 +L56 +R78 +R93 +L28 +L60 +L941 +R110 +L35 +R209 +R71 +R91 +R38 +R88 +L89 +L99 +R36 +R43 +R235 +R65 +L17 +L343 +R81 +R96 +R86 +L790 +R82 +L29 +R414 +R354 +L3 +L99 +R89 +R14 +R195 +L58 +L51 +L46 +L795 +L69 +R10 +L98 +L40 +L70 +R15 +L14 +L22 +R634 +L5 +L73 +L27 +R49 +R851 +R233 +R85 +R782 +L83 +L317 +R314 +L14 +L96 +L204 +L58 +R743 +L468 +R3 +R80 +L69 +R69 +L39 +L18 +R57 +L41 +L59 +R150 +L545 +R13 +R82 +R97 +L97 +R91 +L91 +L2 +L26 +R1 +R47 +L20 +R32 +R68 +L22 +L78 +L41 +L824 +L1 +R66 +R14 +L14 +R2 +R71 +R86 +L72 +R413 +L890 +R290 +L65 +L235 +L95 +R317 +R16 +L13 +R336 +R979 +R15 +R89 +R10 +L254 +R264 +L39 +L71 +L54 +R50 +L38 +L92 +R829 +L351 +L98 +R786 +R21 +R30 +L18 +L579 +L24 +L784 +R20 +R24 +L6 +R12 +R18 +L23 +R923 +L438 +R38 +L91 +L9 +L64 +L36 +L16 +L67 +L17 +R93 +L37 +L93 +R25 +L34 +R63 +L17 +L84 +L47 +L936 +L66 +R3 +R30 +R51 +R49 +L16 +L570 +L34 +L89 +R9 +R89 +R77 +L75 +L91 +R35 +R65 +R12 +R2 +L88 +L226 +R19 +R50 +R36 +L805 +L40 +R564 +L24 +R33 +L32 +R65 +R475 +R59 +L633 +L31 +R64 +L982 +L74 +L51 +R7 +R50 +L50 +R39 +L39 +L16 +R16 +R88 +R278 +R692 +L587 +R29 +L462 +L38 +L96 +L4 +R97 +R78 +R44 +R18 +L18 +R81 +L67 +L33 +R72 +L72 +L23 +R23 +L71 +R49 +L15 +L63 +R64 +L68 +L21 +L10 +L27 +R41 +L65 +R46 +L60 +L73 +L597 +L30 +R71 +L71 +R91 +L58 +L33 +L20 +L492 +R412 +L19 +L50 +R673 +L86 +L76 +R82 +L61 +L63 +R7 +R93 +R646 +R37 +R17 +L331 +R69 +L2 +L768 +L430 +L38 +R498 +L514 +R64 +L59 +L89 +R671 +L71 +R911 +R537 +L48 +R30 +L20 +L10 +R632 +R72 +L16 +L88 +R24 +R97 +R207 +R89 +L89 +L56 +L23 +R52 +L85 +R84 +L16 +R97 +L56 +R75 +L79 +L674 +R79 +L596 +R70 +L96 +L24 +R10 +L90 +R25 +R822 +L47 +R57 +L29 +R1 +L65 +L1 +L26 +L92 +L981 +R40 +R83 +R13 +L14 +R14 +R24 +L231 +R7 +L91 +R80 +L176 +L91 +R78 +R22 +L393 +R127 +L43 +R951 +L64 +R914 +L14 +R17 +R84 +L1 +L35 +R546 +L78 +R75 +L8 +R65 +L815 +L1 +L49 +L9 +L89 +L2 +L412 +L588 +R647 +R25 +L72 +L85 +L15 +L81 +L19 +R21 +R97 +L18 +L14 +R38 +R654 +L774 +L272 +R90 +L36 +R14 +R668 +R343 +R289 +R528 +L28 +L79 +L21 +R21 +L42 +R21 +R219 +L19 +R37 +L67 +R709 +L79 +R731 +L24 +L7 +L431 +L69 +R47 +R79 +R97 +L179 +L380 +L664 +L858 +R4 +L46 +R51 +R149 +R66 +R3 +R831 +R9 +R51 +R93 +L53 +R61 +L81 +L80 +R37 +R163 +L94 +R94 +L394 +R99 +R16 +R779 +R48 +R988 +R79 +R68 +L69 +L73 +L41 +L99 +L81 +R89 +R35 +R62 +R25 +R17 +L48 +R39 +L39 +L6 +L798 +R4 +L646 +R46 +L15 +L85 +L33 +L63 +L21 +R17 +R1 +L351 +L41 +R91 +R13 +L82 +R81 +L22 +L4 +R14 +R23 +L946 +R23 +L81 +R81 +R55 +R45 +R26 +L27 +L46 +R398 +L38 +L513 +R98 +L98 +R95 +R405 +R90 +L32 +R529 +R96 +L27 +R40 +R88 +R50 +L10 +R9 +R57 +L90 +L5 +R246 +R394 +L45 +R10 +R545 +R87 +L44 +R60 +L67 +R61 +R6 +R40 +R12 +L83 +R83 +L41 +L55 +R96 +L921 +L922 +R43 +L82 +L18 +R28 +L28 +R871 +R312 +R31 +L55 +R82 +L22 +L627 +L75 +R12 +L91 +R62 +R56 +R61 +R48 +R35 +L385 +L842 +L77 +L96 +R816 +R669 +R49 +R31 +L94 +R74 +L72 +R24 +L5 +R8 +L57 +L43 +L82 +R26 +L16 +L928 +R83 +R17 +L602 +L35 +L889 +R26 +L53 +L38 +L18 +L734 +L42 +L86 +L38 +L76 +L679 +R94 +L630 +R76 +R484 +L70 +R24 +R34 +R17 +L365 +L190 +R69 +L79 +L76 +R910 +R66 +L57 +R423 +R407 +R13 +R36 +R28 +R50 +L235 +L491 +L92 +R73 +R52 +L7 +L86 +R421 +L75 +L48 +L37 +L970 +L505 +R60 +L95 +L65 +R42 +L64 +L78 +R93 +R7 +R427 +R48 +R861 +R764 +R88 +R286 +L591 +L446 +L37 +L91 +R47 +L56 +R92 +L92 +R90 +R748 +R8 +L225 +L665 +L32 +R9 +L833 +R7 +L7 +R576 +L39 +R928 +R35 +L59 +R59 +R18 +R35 +L53 +R805 +L56 +L74 +R25 +L345 +L21 +L75 +L48 +R40 +R93 +L36 +R238 +R54 +L38 +R29 +R26 +L17 +R6 +R94 +L54 +L30 +L6 +R648 +R5 +R37 +L80 +R78 +L1 +R3 +L46 +R65 +R3 +R78 +L61 +R31 +L70 +L69 +L31 +L88 +R92 +R96 +L81 +R67 +R25 +L11 +R59 +L615 +R108 +R748 +R40 +L922 +R78 +R32 +R15 +R77 +L20 +L8 +L18 +R18 +L92 +R40 +R60 +R8 +R87 +R2 +R3 +L1 +R1 +R61 +R71 +L32 +L73 +R73 +R82 +L62 +R2 +R78 +L31 +L234 +L35 +R41 +R219 +L67 +R7 +R91 +L3 +L28 +R86 +L91 +R89 +R87 +L493 +R62 +R57 +L290 +R33 +L31 +R31 +R49 +L49 +R48 +R829 +L221 +R94 +L32 +R66 +L684 +L94 +L65 +R36 +L28 +R51 +L83 +L30 +L817 +L334 +R12 +R12 +L15 +R13 +R21 +R65 +R56 +R29 +L99 +L30 +L96 +L4 +L79 +R1 +L16 +R94 +L70 +R93 +L3 +R63 +R96 +L79 +R17 +L917 +R13 +R52 +L5 +L60 +R37 +L88 +L249 +R10 +R90 +L33 +R87 +L66 +R93 +L13 +R32 +R25 +R40 +L6 +L65 +R306 +L55 +L91 +L28 +L26 +L31 +R37 +L66 +L927 +L58 +L57 +L98 +L31 +L69 +L559 +R892 +L33 +R62 +R38 +R78 +L78 +R13 +R87 +R90 +R877 +L81 +R61 +R26 +L573 +R36 +R64 +L35 +R35 +R29 +R47 +R232 +R85 +L2 +L91 +L22 +R89 +L67 +R37 +R91 +L97 +L31 +L67 +L993 +L74 +R34 +R48 +R72 +L63 +R43 +R52 +L52 +L75 +R84 +R56 +L69 +R4 +L41 +R52 +L87 +R76 +R563 +R8 +R29 +R87 +L97 +R10 +R78 +R17 +L295 +L22 +R22 +R31 +R17 +R17 +R435 +R47 +R851 +L898 +L81 +L509 +R3 +L87 +R174 +L52 +R52 +R31 +R552 +L225 +R26 +R10 +L131 +L688 +L52 +R7 +L94 +L36 +R96 +R4 +L46 +R87 +L46 +L10 +R984 +R86 +R45 +R38 +L38 +R72 +R34 +L440 +L366 +R38 +R462 +L410 +R42 +L35 +R56 +L411 +L35 +R93 +R313 +L93 +L31 +L44 +L74 +R83 +L254 +L7 +L49 +R70 +R986 +L93 +R93 +L43 +R83 +L6 +R32 +R73 +L239 +L65 +L83 +L1 +R249 +L882 +L13 +R29 +R151 +R15 +L99 +R99 +R14 +L18 +L76 +R80 +L92 +L50 +R42 +R52 +R893 +L29 +L16 +R31 +R22 +L553 +L41 +R41 +R71 +L71 +L6 +L39 +L2 +L83 +R64 +L94 +L71 +L72 +R403 +L6 +R6 +R84 +R16 +L68 +L60 +R2 +L3 +R18 +L39 +L50 +R47 +L37 +R543 +R30 +R247 +R21 +R78 +R788 +R83 +L18 +L82 +L49 +R10 +L69 +R599 +R9 +R40 +R9 +R751 +R76 +R40 +L16 +L741 +R54 +L13 +R13 +R741 +L46 +R86 +R96 +R221 +R61 +R79 +L66 +R27 +R98 +L10 +L48 +L52 +L639 +R39 +R7 +R71 +L79 +R1 +R76 +L76 +L98 +R14 +L16 +R72 +R81 +R87 +L44 +R4 +R71 +R90 +L57 +R85 +R63 +L13 +R61 +L75 +R52 +L14 +L63 +R56 +R952 +L264 +L510 +L434 +R440 +L77 +L63 +R338 +R227 +L23 +L59 +R81 +R36 +R83 +R71 +R275 +L63 +R911 +L447 +R289 +R281 +L72 +L928 +R28 +R90 +R77 +L995 +R33 +R29 +R86 +L99 +L49 +L152 +L12 +R2 +R58 +R36 +R68 +L83 +L311 +L53 +L63 +L562 +L28 +L7 +R8 +R33 +R71 +R52 +R643 +R97 +R3 +L640 +L802 +L74 +R95 +L51 +R49 +R5 +L82 +L49 +L21 +R70 +R587 +L87 +R37 +L18 +R81 +R386 +L8 +R22 +L962 +R295 +L825 +L8 +R52 +R48 +R32 +L93 +L63 +L76 +L6 +L980 +R86 +R913 +R87 +L94 +L44 +R79 +L8 +R8 +R34 +R928 +L93 +R590 +L50 +L66 +R64 +L1 +R449 +R41 +R731 +L68 +L18 +L11 +L95 +R6 +R18 +R140 +R92 +L32 +L9 +L6 +L6 +R21 +L56 +R78 +R2 +L82 +L42 +L61 +L39 +R1 +L1 +R82 +L35 +L32 +L15 +L43 +L86 +L26 +R55 +L14 +L86 +L78 +R79 +R628 +R71 +R63 +R65 +R75 +L447 +R63 +L27 +R24 +R27 +R33 +R24 +L26 +L74 +R53 +L7 +R54 +L14 +R51 +L76 +R66 +R76 +L97 +L978 +L57 +R29 +L17 +R54 +L998 +R99 +L8 +L130 +R88 +L888 +L33 +R24 +R9 +R32 +R168 +R90 +R920 +L29 +L95 +R14 +R79 +R78 +L46 +L36 +L75 +L39 +R39 +L87 +R5 +R82 +R90 +R62 +L52 +L16 +R28 +R21 +R42 +R25 +R472 +R82 +R611 +L634 +R344 +L27 +L20 +R73 +L87 +L73 +L85 +L756 +L376 +R25 +L98 +L52 +R97 +L144 +L61 +R9 +R697 +R58 +R66 +R272 +R61 +L75 +L479 +L778 +L737 +R31 +L16 +L77 +L776 +R39 +R832 +L18 +L66 +L553 +R21 +R481 +L84 +L499 +R59 +L116 +L65 +R24 +L91 +L11 +R20 +L61 +L659 +L759 +R9 +L73 +L77 +R75 +R25 +L190 +L50 +R40 +R21 +R17 +R8 +R91 +R861 +L89 +R51 +L86 +L4 +R3 +R10 +R75 +R53 +R2 +R87 +L89 +L26 +L96 +R729 +L561 +R43 +R42 +L53 +L89 +L18 +L48 +R241 +R225 +L24 +R624 +L51 +R8 +R54 +R99 +L98 +R188 +L267 +L533 +L63 +R63 +L46 +R10 +L40 +R20 +L99 +L72 +R92 +R3 +R8 +L34 +L93 +R344 +R7 +L35 +R33 +R76 +R26 +R25 +L7 +L31 +L299 +L990 +L95 +R14 +R42 +L344 +L91 +L24 +L84 +R316 +R357 +L40 +R99 +L10 +L52 +R4 +R10 +L846 +L54 +L4 +R55 +R20 +L71 +R80 +R61 +R86 +R73 +R74 +R26 +R538 +L62 +R22 +L398 +R73 +R84 +L73 +L184 +L38 +R51 +L513 +R80 +R62 +L631 +L467 +L13 +R69 +L688 +L39 +L73 +R35 +L845 +R819 +L98 +R89 +L551 +R51 +R28 +R72 +L73 +L991 +R16 +L989 +L65 +R2 +L37 +L134 +L88 +R59 +R75 +L43 +R368 +L434 +L66 +L61 +R83 +R15 +L63 +R466 +R60 +L299 +L25 +R3 +R32 +R89 +R46 +L81 +L70 +R5 +R33 +R59 +R108 +L77 +L913 +L25 +L96 +L80 +R8 +R29 +R954 +R45 +R50 +L14 +L28 +L16 +R83 +L379 +L74 +R74 +R59 +R99 +R76 +L62 +L57 +L83 +L73 +R41 +L326 +R85 +L91 +L609 +R66 +L79 +R557 +R56 +R50 +L70 +L31 +R506 +L55 +L715 +R15 +L67 +R5 +L76 +R10 +L18 +R348 +L579 +L59 +R12 +R38 +R9 +R29 +R748 +R52 +L70 +R705 +R13 +R86 +R97 +R17 +L77 +L745 +R222 +R84 +L84 +R5 +R858 +L68 +R5 +L30 +L42 +L65 +R37 +R801 +L66 +R2 +R54 +R9 +L37 +L16 +L702 +L7 +L2 +R164 +R92 +L79 +R387 +R30 +L19 +L79 +R43 +R284 +L75 +R27 +L711 +R72 +R156 +R72 +L57 +R63 +L95 +L55 +L250 +L6 +L73 +R559 +R11 +R3 +L13 +R37 +R16 +R60 +L12 +R54 +L275 +R33 +L8 +R493 +R10 +L95 +L20 +L180 +R34 +R66 +L56 +R56 +L76 +L324 +R42 +L42 +L247 +R65 +R82 +R5 +L12 +R165 +L18 +L79 +R39 +L174 +L26 +R441 +R18 +R7 +R533 +L752 +L54 +R71 +R16 +L80 +R75 +L92 +R44 +L827 +L90 +L50 +R56 +L72 +R92 +R80 +L16 +L85 +L51 +L42 +L20 +R86 +R44 +L927 +L705 +R786 +L76 +L99 +L1 +R64 +L86 +L88 +R1 +R99 +L69 +R69 +L32 +L16 +R48 +L97 +R97 +L35 +R35 +L9 +L64 +R9 +R55 +L91 +L22 +R71 +R48 +R3 +R39 +R68 +L86 +L72 +R74 +L23 +R84 +L46 +L38 +R70 +R99 +L50 +L13 +R5 +R91 +L2 +R17 +R51 +R32 +R11 +L11 +R39 +L26 +R93 +R24 +L43 +R67 +L45 +L9 +L33 +R13 +L21 +R48 +R44 +R3 +R19 +R47 +L8 +R17 +R12 +R45 +L42 +R8 +R38 +L20 +R7 +R20 +L25 +R20 +R22 +R28 +L27 +L5 +L39 +L6 +L17 +L42 +R29 +R49 +L50 +L5 +R31 +R49 +L16 +R20 +L27 +R16 +R27 +L37 +R45 +R32 +L30 +L43 +L39 +R29 +R33 +R32 +L34 +R31 \ No newline at end of file diff --git a/2025/go/go.mod b/2025/go/go.mod new file mode 100644 index 0000000..9674ea9 --- /dev/null +++ b/2025/go/go.mod @@ -0,0 +1,16 @@ +module adventofcode2025 + +go 1.23.2 + +toolchain go1.23.5 + +require ( + github.com/stretchr/testify v1.11.1 + golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/2025/go/go.sum b/2025/go/go.sum new file mode 100644 index 0000000..f7bca47 --- /dev/null +++ b/2025/go/go.sum @@ -0,0 +1,11 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/2025/go/main.go b/2025/go/main.go new file mode 100644 index 0000000..e896259 --- /dev/null +++ b/2025/go/main.go @@ -0,0 +1,154 @@ +package main + +import ( + "fmt" + "time" + + // "math/rand" + "os" + // "strings" + // "time" + "adventofcode2025/day01" + "adventofcode2025/utils" +) + +// Usage: go run main.go +// assumes input is in day/input.txt +func main() { + d := day() + fmt.Printf("Running day %02d\n", d) + start := time.Now() + switch d { + case 1: + fmt.Printf("part 1: %d\n", day01.Part1(utils.Readfile(d))) + fmt.Printf("part 2: %d\n", day01.Part2(utils.Readfile(d))) +// case 2: +// fmt.Printf("part 1: %d\n", day02.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day02.Part2(utils.Readfile(d))) +// case 3: +// fmt.Printf("part 1: %d\n", day03.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day03.Part2(utils.Readfile(d))) +// case 4: +// fmt.Printf("part 1: %d\n", day04.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day04.Part2(utils.Readfile(d))) +// case 6: +// fmt.Printf("part 1: %d\n", day06.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day06.Part2(utils.Readfile(d))) +// case 7: +// fmt.Printf("part 1: %d\n", day07.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day07.Part2(utils.Readfile(d))) +// case 8: +// fmt.Printf("part 1: %d\n", day08.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day08.Part2(utils.Readfile(d))) +// case 9: +// fmt.Printf("part 1: %d\n", day09.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day09.Part2(utils.Readfile(d))) +// case 10: +// fmt.Printf("part 1: %d\n", day10.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day10.Part2(utils.Readfile(d))) +// case 11: +// fmt.Printf("part 1: %d\n", day11.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day11.Part2(utils.Readfile(d))) +// case 12: +// fmt.Printf("part 1: %d\n", day12.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day12.Part2(utils.Readfile(d))) +// case 13: +// fmt.Printf("part 1: %d\n", day13.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day13.Part2(utils.Readfile(d))) +// case 14: +// fmt.Printf("part 1: %d\n", day14.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day14.Part2(utils.Readfile(d))) +// case 15: +// fmt.Printf("part 1: %d\n", day15.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day15.Part2(utils.Readfile(d))) +// case 16: +// fmt.Printf("part 1: %d\n", day16.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day16.Part2(utils.Readfile(d))) +// case 17: +// fmt.Printf("part 1: %s\n", day17.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day17.Part2(utils.Readfile(d))) +// case 18: +// fmt.Printf("part 1: %d\n", day18.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day18.Part2(utils.Readfile(d))) +// case 19: +// fmt.Printf("part 1: %d\n", day19.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day19.Part2(utils.Readfile(d))) +// case 21: +// fmt.Printf("part 1: %d\n", day21.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day21.Part2(utils.Readfile(d))) +// case 22: +// fmt.Printf("part 1: %d\n", day22.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day22.Part2(utils.Readfile(d))) +// case 23: +// fmt.Printf("part 1: %d\n", day23.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day23.Part2(utils.Readfile(d))) +// case 24: +// fmt.Printf("part 1: %d\n", day24.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day24.Part2(utils.Readfile(d))) +// case 25: +// fmt.Printf("part 1: %d\n", day25.Part1(utils.Readfile(d))) +// fmt.Printf("part 2: %d\n", day25.Part2(utils.Readfile(d))) + default: + panic(fmt.Errorf("no such day: %d", d)) + } + elapsed := time.Since(start) + fmt.Printf("Execution time: %s\n", elapsed) +} + +// Reads day from os.Args. +func day() int { + latest := 0 + if len(os.Args) == 1 { + return latest + } + + if os.Args[1] == "next" { + genNext(latest + 1) + os.Exit(0) + } + day := utils.MustAtoi(os.Args[1]) + return day +} + +func genNext(n int) { + os.Mkdir(fmt.Sprintf("day%02d", n), 0755) + f, err := os.Create(fmt.Sprintf("day%02d/day%02d.go", n, n)) + utils.PanicOnErr(err) + defer f.Close() + f.WriteString(fmt.Sprintf(`package day%02d + +func Part1(input string) int { + return 0 +} + +func Part2(input string) int { + return 0 +} +`, n)) + fmt.Printf("wrote day%02d/day%02d.go\n", n, n) + + f, err = os.Create(fmt.Sprintf("day%02d/day%02d_test.go", n, n)) + utils.PanicOnErr(err) + defer f.Close() + f.WriteString(fmt.Sprintf(`package day%02d + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestPart1(t *testing.T) { + r := Part1("") + require.Equal(t, 0, r) +} + +func TestPart2(t *testing.T) { + r := Part2("") + require.Equal(t, 0, r) +} +`, n)) + fmt.Printf("wrote day%02d/day%02d_test.go\n", n, n) + utils.GenInputFile(n) + +} diff --git a/2025/go/utils/dijkstra/graph.go b/2025/go/utils/dijkstra/graph.go new file mode 100644 index 0000000..1836523 --- /dev/null +++ b/2025/go/utils/dijkstra/graph.go @@ -0,0 +1,241 @@ +package dijkstra + +import ( + "math" + "sync" +) + +type ItemGraph struct { + Nodes []*Node + Edges map[Node][]*Edge + lock sync.RWMutex +} + +// AddNode adds a node to the graph +func (g *ItemGraph) AddNode(n *Node) { + g.lock.Lock() + g.Nodes = append(g.Nodes, n) + g.lock.Unlock() +} + +// AddEdge adds an edge to the graph +func (g *ItemGraph) AddEdge(n1, n2 *Node, weight int) { + g.lock.Lock() + if g.Edges == nil { + g.Edges = make(map[Node][]*Edge) + } + ed1 := Edge{ + Node: n2, + Weight: weight, + } + + ed2 := Edge{ + Node: n1, + Weight: weight, + } + g.Edges[*n1] = append(g.Edges[*n1], &ed1) + g.Edges[*n2] = append(g.Edges[*n2], &ed2) + g.lock.Unlock() +} + +// dijkstra implement +func getShortestPath(startNode *Node, endNode *Node, g *ItemGraph) ([]Point, int) { + visited := make(map[Point]bool) + dist := make(map[Point]int) + prev := make(map[Point]Point) + //pq := make(PriorityQueue, 1) + //heap.Init(&pq) + q := NodeQueue{} + pq := q.NewQ() + start := Vertex{ + Node: startNode, + Distance: 0, + } + for _, nval := range g.Nodes { + dist[nval.Value] = math.MaxInt64 + } + dist[startNode.Value] = start.Distance + pq.Enqueue(start) + //im := 0 + for !pq.IsEmpty() { + v := pq.Dequeue() + if visited[v.Node.Value] { + continue + } + visited[v.Node.Value] = true + near := g.Edges[*v.Node] + + for _, val := range near { + if !visited[val.Node.Value] { + if dist[v.Node.Value]+val.Weight < dist[val.Node.Value] { + store := Vertex{ + Node: val.Node, + Distance: dist[v.Node.Value] + val.Weight, + } + dist[val.Node.Value] = dist[v.Node.Value] + val.Weight + //prev[val.Node.Value] = fmt.Sprintf("->%s", v.Node.Value) + prev[val.Node.Value] = v.Node.Value + pq.Enqueue(store) + } + //visited[val.Node.value] = true + } + } + } + // fmt.Println(dist) + // fmt.Println(prev) + pathval := prev[endNode.Value] + var finalArr []Point + finalArr = append(finalArr, endNode.Value) + for pathval != startNode.Value { + finalArr = append(finalArr, pathval) + pathval = prev[pathval] + } + finalArr = append(finalArr, pathval) + // fmt.Println(finalArr) + for i, j := 0, len(finalArr)-1; i < j; i, j = i+1, j-1 { + finalArr[i], finalArr[j] = finalArr[j], finalArr[i] + } + return finalArr, dist[endNode.Value] + +} + +func getAllShortestPaths(startNode *Node, endNode *Node, g *ItemGraph) ([][]Point, int) { + visited := make(map[Point]bool) + dist := make(map[Point]int) + prev := make(map[Point][]Point) // Store multiple predecessors for each node + q := NodeQueue{} + pq := q.NewQ() + + start := Vertex{ + Node: startNode, + Distance: 0, + } + + for _, n := range g.Nodes { + dist[n.Value] = math.MaxInt64 + } + dist[startNode.Value] = start.Distance + pq.Enqueue(start) + + // Perform Dijkstra's algorithm + for !pq.IsEmpty() { + v := pq.Dequeue() + if visited[v.Node.Value] { + continue + } + visited[v.Node.Value] = true + near := g.Edges[*v.Node] + + for _, edge := range near { + alt := dist[v.Node.Value] + edge.Weight + + // Case 1: Found a shorter path + if alt < dist[edge.Node.Value] { + dist[edge.Node.Value] = alt + prev[edge.Node.Value] = []Point{v.Node.Value} // Reset predecessors + pq.Enqueue(Vertex{ + Node: edge.Node, + Distance: alt, + }) + } + + // Case 2: Found an equally short path + if alt == dist[edge.Node.Value] { + // Add the current node as a valid predecessor if not already present + found := false + for _, p := range prev[edge.Node.Value] { + if p == v.Node.Value { + found = true + break + } + } + if !found { + prev[edge.Node.Value] = append(prev[edge.Node.Value], v.Node.Value) + } + } + } + } + + // Iteratively reconstruct all paths + var paths [][]Point + stack := []struct { + node Point + path []Point + }{ + {node: endNode.Value, path: []Point{}}, + } + + for len(stack) > 0 { + // Pop the top item from the stack + current := stack[len(stack)-1] + stack = stack[:len(stack)-1] + + // Prepend the current node to the path + newPath := append([]Point{current.node}, current.path...) + + // If we've reached the start node, save the path + if current.node.X == startNode.Value.X && current.node.Y == startNode.Value.Y { + paths = append(paths, newPath) + continue + } + + // Push all predecessors onto the stack + for _, predecessor := range prev[current.node] { + if !Contains(newPath, predecessor) { + stack = append(stack, struct { + node Point + path []Point + }{ + node: predecessor, + path: newPath, + }) + } + } + } + + return paths, dist[endNode.Value] +} + +func Contains(slice []Point, value Point) bool { + for _, v := range slice { + if v == value { // Compare values + return true + } + } + return false +} + +func CreateGraph(data InputGraph) *ItemGraph { + var g ItemGraph + nodes := make(map[Point]*Node) + for _, v := range data.Graph { + if _, found := nodes[v.Source]; !found { + nA := Node{v.Source} + nodes[v.Source] = &nA + g.AddNode(&nA) + } + if _, found := nodes[v.Destination]; !found { + nA := Node{v.Destination} + nodes[v.Destination] = &nA + g.AddNode(&nA) + } + g.AddEdge(nodes[v.Source], nodes[v.Destination], v.Weight) + } + return &g +} + +func GetShortestPath(from, to Point, g *ItemGraph) ([]Point, int) { + nA := &Node{from} + nB := &Node{to} + + path, distance := getShortestPath(nA, nB, g) + return path, distance +} + +func GetAllShortestPaths(from, to Point, g *ItemGraph) ([][]Point, int) { + nA := &Node{from} + nB := &Node{to} + + paths, distance := getAllShortestPaths(nA, nB, g) + return paths, distance +} diff --git a/2025/go/utils/dijkstra/object.go b/2025/go/utils/dijkstra/object.go new file mode 100644 index 0000000..689635f --- /dev/null +++ b/2025/go/utils/dijkstra/object.go @@ -0,0 +1,35 @@ +package dijkstra + +type Point struct { + X int + Y int + Label string +} + +type Node struct { + Value Point +} + +type Edge struct { + Node *Node + Weight int +} + +type Vertex struct { + Node *Node + Distance int +} + +type PriorityQueue []*Vertex + +type InputGraph struct { + Graph []InputData + From Point + To Point +} + +type InputData struct { + Source Point + Destination Point + Weight int +} \ No newline at end of file diff --git a/2025/go/utils/dijkstra/queue.go b/2025/go/utils/dijkstra/queue.go new file mode 100644 index 0000000..c893e01 --- /dev/null +++ b/2025/go/utils/dijkstra/queue.go @@ -0,0 +1,65 @@ +package dijkstra + +import "sync" + +type NodeQueue struct { + Items []Vertex + lock sync.RWMutex +} + +// Enqueue adds an Node to the end of the queue +func (s *NodeQueue) Enqueue(t Vertex) { + s.lock.Lock() + defer s.lock.Unlock() + + if len(s.Items) == 0 { + s.Items = append(s.Items, t) + return + } + var insertFlag bool + for k, v := range s.Items { + // add vertex distance less than travers's vertex distance + if t.Distance < v.Distance { + s.Items = append(s.Items[:k+1], s.Items[k:]...) + s.Items[k] = t + insertFlag = true + } + if insertFlag { + break + } + } + if !insertFlag { + s.Items = append(s.Items, t) + } +} + +// Dequeue removes an Node from the start of the queue +func (s *NodeQueue) Dequeue() *Vertex { + s.lock.Lock() + defer s.lock.Unlock() + item := s.Items[0] + s.Items = s.Items[1:len(s.Items)] + return &item +} + +//NewQ Creates New Queue +func (s *NodeQueue) NewQ() *NodeQueue { + s.lock.Lock() + defer s.lock.Unlock() + s.Items = []Vertex{} + return s +} + +// IsEmpty returns true if the queue is empty +func (s *NodeQueue) IsEmpty() bool { + s.lock.RLock() + defer s.lock.RUnlock() + return len(s.Items) == 0 +} + +// Size returns the number of Nodes in the queue +func (s *NodeQueue) Size() int { + s.lock.RLock() + defer s.lock.RUnlock() + return len(s.Items) +} \ No newline at end of file diff --git a/2025/go/utils/grid2d/grid2d.go b/2025/go/utils/grid2d/grid2d.go new file mode 100644 index 0000000..aff1da3 --- /dev/null +++ b/2025/go/utils/grid2d/grid2d.go @@ -0,0 +1,77 @@ +package grid2d + +import ( + "strings" + + "adventofcode2024/utils" +) + +type Grid[T any] struct { + sizeX, sizeY int + matrix [][]T + empty T +} + +func NewGrid[T any](sizeX, sizeY int, empty T) *Grid[T] { + matrix := make([][]T, sizeY) + rows := make([]T, sizeX*sizeY) + for i := 0; i < sizeX*sizeY; i++ { + rows[i] = empty + } + + j := 0 + for i := 0; i < sizeY; i++ { + matrix[i] = rows[j : j+sizeX : j+sizeX] + j += sizeX + } + return &Grid[T]{ + sizeX: sizeX, + sizeY: sizeY, + matrix: matrix, + empty: empty, + } +} + +func (g *Grid[T]) SizeX() int { + return g.sizeX +} + +func (g *Grid[T]) SizeY() int { + return g.sizeY +} +func (g *Grid[T]) Matrix() [][]T { + return g.matrix +} + +func (g *Grid[T]) Get(x, y int) T { + if x < 0 || x >= g.sizeX { + return g.empty + } + if y < 0 || y >= g.sizeY { + return g.empty + } + return g.matrix[y][x] +} + +func (g *Grid[T]) Set(x, y int, v T) { + if x < 0 || x >= g.sizeX { + panic("invalid x") + } + if y < 0 || y >= g.sizeY { + panic("invalid y") + } + g.matrix[y][x] = v +} + +func (g *Grid[T]) StringWithFormatter(formatter func(T, int, int) string) string { + var r strings.Builder + for j := 0; j < g.sizeY; j++ { + for i := 0; i < g.sizeX; i++ { + _, err := r.WriteString(formatter(g.matrix[j][i], i, j)) + utils.PanicOnErr(err) + } + _, err := r.WriteRune('\n') + utils.PanicOnErr(err) + } + return r.String() +} diff --git a/2025/go/utils/inputFile.go b/2025/go/utils/inputFile.go new file mode 100644 index 0000000..a5ec84b --- /dev/null +++ b/2025/go/utils/inputFile.go @@ -0,0 +1,63 @@ +package utils + +import ( + "fmt" + "io" + "net/http" + "os" +) + +func GenInputFile(day int) string { + var d string + if day < 10 { + d = fmt.Sprintf("0%d", day) + } else { + d = fmt.Sprintf("%d", day) + } + + pwd, _ := os.Getwd() + path := fmt.Sprintf("%s/day%s/input.txt", pwd, d) + fi, _ := os.Stat(path) + if fi != nil { + return path + } + + fmt.Printf("Creating new input file %v...", path) + f, err := os.Create(path) + if err != nil { + fmt.Println(err) + } else { + defer f.Close() + data := readHttp(2025, day) + _, err := f.WriteString(data) + if err != nil { + fmt.Println(err) + } + } + return path +} + +func readHttp(year, day int) string { + fmt.Println("Fetching data into file...") + + url := fmt.Sprintf("https://adventofcode.com/%d/day/%d/input", year, day) + session := os.Getenv("sessionAoC") + req, err := http.NewRequest("GET", url, nil) + if err != nil { + panic(err) + } + + req.AddCookie(&http.Cookie{Name: "session", Value: session}) + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + panic(err) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + panic(err) + } + return string(body) +} + diff --git a/2025/go/utils/inputs/inputs.go b/2025/go/utils/inputs/inputs.go new file mode 100644 index 0000000..cf7457c --- /dev/null +++ b/2025/go/utils/inputs/inputs.go @@ -0,0 +1,56 @@ +package inputs + +import ( + "strings" + + "adventofcode2024/utils" + "adventofcode2024/utils/grid2d" + sparsegrid "adventofcode2024/utils/sparseGrid" +) + +func ToInts(input string, sep string) []int { + var r []int + for _, line := range strings.Split(input, sep) { + if line != "" { + r = append(r, utils.MustAtoi(line)) + } + } + return r +} + +func ToGrid2D[T any](input, rowSep, colSep string, empty T, conv func(string) T) *grid2d.Grid[T] { + + var width int + + lines := strings.Split(input, rowSep) + + if colSep == "" { + // If no colSep, width is the length of each line + width = len(lines[0]) + } else { + // Use colSep to determine the width of the grid + width = len(strings.Split(lines[0], colSep)) + } + + grid := grid2d.NewGrid(width, len(lines), empty) + for y, line := range lines { + for x, v := range strings.Split(line, colSep) { + grid.Set(x, y, conv(v)) + } + } + + return grid +} + +func ToSparseGrid[T comparable](input, rowSep, colSep string, empty T, conv func(string) T) *sparsegrid.SparseGrid[T] { + lines := strings.Split(input, rowSep) + + grid := sparsegrid.NewGrid(empty) + for y, line := range lines { + for x, v := range strings.Split(line, colSep) { + grid.Set(x, y, conv(v)) + } + } + + return grid +} diff --git a/2025/go/utils/memo/memo.go b/2025/go/utils/memo/memo.go new file mode 100644 index 0000000..de52d55 --- /dev/null +++ b/2025/go/utils/memo/memo.go @@ -0,0 +1,47 @@ +package memo + +import "sync" + +type Func func(key interface{}) interface{} + +type result struct { + value interface{} +} + +type Memo struct { + f Func + cache map[interface{}]result + mu sync.RWMutex // Allows concurrent reads. +} + +func New(f Func) *Memo { + return &Memo{ + f: f, + cache: make(map[interface{}]result), + } +} + +func (memo *Memo) Get(key interface{}) interface{} { + // First, try to read the cache using a read lock. + memo.mu.RLock() + res, ok := memo.cache[key] + memo.mu.RUnlock() + if ok { + return res.value + } + + // Compute the result without holding the lock. + computed := memo.f(key) + + // Now acquire a write lock to update the cache. + memo.mu.Lock() + // Double-check: another goroutine may have stored the result in the meantime. + res, ok = memo.cache[key] + if !ok { + res.value = computed + memo.cache[key] = res + } + memo.mu.Unlock() + + return res.value +} diff --git a/2025/go/utils/ringbuffer/ringbuffer.go b/2025/go/utils/ringbuffer/ringbuffer.go new file mode 100644 index 0000000..70724c9 --- /dev/null +++ b/2025/go/utils/ringbuffer/ringbuffer.go @@ -0,0 +1,56 @@ +package ringbuffer + +import ( + "sync" +) + +type RingBuffer[T any] struct { + buffer []T + size int + mu sync.Mutex + write int + count int +} + +// NewRingBuffer creates a new ring buffer with a fixed size. +func NewRingBuffer[T any](size int) *RingBuffer[T] { + return &RingBuffer[T]{ + buffer: make([]T, size), + size: size, + } +} + +// Add inserts a new element into the buffer, overwriting the oldest if full. +func (rb *RingBuffer[T]) Add(value T) { + rb.mu.Lock() + defer rb.mu.Unlock() + + rb.buffer[rb.write] = value + rb.write = (rb.write + 1) % rb.size + + if rb.count < rb.size { + rb.count++ + } +} + +// Get returns the contents of the buffer in FIFO order. +func (rb *RingBuffer[T]) Get() []T { + rb.mu.Lock() + defer rb.mu.Unlock() + + result := make([]T, 0, rb.count) + + for i := 0; i < rb.count; i++ { + index := (rb.write + rb.size - rb.count + i) % rb.size + result = append(result, rb.buffer[index]) + } + + return result +} + +// Len returns the current number of elements in the buffer. +func (rb *RingBuffer[T]) Len() int { + rb.mu.Lock() + defer rb.mu.Unlock() + return rb.count +} diff --git a/2025/go/utils/sparseGrid/sparseGrid.go b/2025/go/utils/sparseGrid/sparseGrid.go new file mode 100644 index 0000000..c7fbb6f --- /dev/null +++ b/2025/go/utils/sparseGrid/sparseGrid.go @@ -0,0 +1,81 @@ +package sparsegrid + +import ( + "fmt" + "strings" + + "adventofcode2024/utils" +) + +type SparseGrid[T comparable] struct { + minX, maxX, minY, maxY int + data map[string]T + empty T +} + +func NewGrid[T comparable](empty T) *SparseGrid[T] { + return &SparseGrid[T]{ + minX: utils.MaxInt, + maxX: utils.MinInt, + minY: utils.MaxInt, + maxY: utils.MinInt, + data: map[string]T{}, + empty: empty, + } +} + +func (g *SparseGrid[T]) SizeX() (int, int) { + return g.minX, g.maxX +} + +func (g *SparseGrid[T]) SizeY() (int, int) { + return g.minY, g.maxY +} + +func (g *SparseGrid[T]) Visited() int { + return len(g.data) +} + +func (g *SparseGrid[T]) Get(x, y int) T { + k := key(x, y) + v, ok := g.data[k] + if !ok { + return g.empty + } + return v +} + +func (g *SparseGrid[T]) Set(x, y int, v T) { + k := key(x, y) + current, ok := g.data[k] + if ok && v == current { + return + } else if !ok && v == g.empty { + return + } else if v == g.empty { + delete(g.data, k) + } else { + g.data[k] = v + g.minX = utils.Min(g.minX, x) + g.maxX = utils.Max(g.maxX, x) + g.minY = utils.Min(g.minY, y) + g.maxY = utils.Max(g.maxY, y) + } +} + +func (g *SparseGrid[T]) StringWithFormatter(formatter func(T, int, int) string) string { + var r strings.Builder + for j := g.minY; j <= g.maxY; j++ { + for i := g.minX; i <= g.maxX; i++ { + _, err := r.WriteString(formatter(g.Get(i, j), i, j)) + utils.PanicOnErr(err) + } + _, err := r.WriteRune('\n') + utils.PanicOnErr(err) + } + return r.String() +} + +func key(x, y int) string { + return fmt.Sprintf("%d:%d", x, y) +} diff --git a/2025/go/utils/utils.go b/2025/go/utils/utils.go new file mode 100644 index 0000000..14d1797 --- /dev/null +++ b/2025/go/utils/utils.go @@ -0,0 +1,222 @@ +package utils + +import ( + "bufio" + "fmt" + "io" + "os" + "reflect" + "regexp" + "strconv" + "strings" + + "golang.org/x/exp/constraints" +) + +func PanicOnErr(err error) { + if err != nil { + panic(err) + } +} + +const MaxInt = int(^uint(0) >> 1) +const MinInt = ^MaxInt + +func Max[T constraints.Ordered](a, b T) T { + if a > b { + return a + } + return b +} + +func Min[T constraints.Ordered](a, b T) T { + if a < b { + return a + } + return b +} + +func SliceMinMax[T constraints.Ordered](slice []T) (*T, *T) { + if len(slice) == 0 { + return nil, nil + } + min := &slice[0] + max := &slice[0] + for i, v := range slice { + if v < *min { + min = &slice[i] + } + if v > *max { + max = &slice[i] + } + } + return min, max +} + +func MustAtoi(s string) int { + v, err := strconv.Atoi(s) + PanicOnErr(err) + return v +} + +// Returns key from map[T]int which has the max value +func MapFindMax(m interface{}) interface{} { + var maxK interface{} = nil + var maxV = MinInt + iter := reflect.ValueOf(m).MapRange() + for iter.Next() { + k := iter.Key() + v := int(iter.Value().Int()) + if v > maxV { + maxV = v + maxK = k.Interface() + } + } + return maxK +} + +// Returns key from map[T]int which has the min value +func MapFindMin(m interface{}) interface{} { + var minK interface{} = nil + var minV = MaxInt + iter := reflect.ValueOf(m).MapRange() + for iter.Next() { + k := iter.Key() + v := int(iter.Value().Int()) + if v < minV { + minV = v + minK = k.Interface() + } + } + return minK +} + +func Readfile(day int) string { + filename := fmt.Sprintf("day%02d/input.txt", day) + file, err := os.Open(filename) + PanicOnErr(err) + defer file.Close() + + reader := bufio.NewReader(file) + contents, err := io.ReadAll(reader) + PanicOnErr(err) + + return strings.TrimSuffix(string(contents), "\n") +} + +func ReadfileAsSlice(day int) []string { + filename := fmt.Sprintf("day%02d/input.txt", day) + file, err := os.Open(filename) + PanicOnErr(err) + defer file.Close() + + arr := make([]string, 0) + sc := bufio.NewScanner(file) + for sc.Scan() { + arr = append(arr, sc.Text()) + } + + return arr +} + +func ParseToStruct(re *regexp.Regexp, input string, target interface{}) bool { + m := re.FindStringSubmatch(input) + if m == nil { + return false + } + + var useOffset bool + + for i, name := range re.SubexpNames() { + if i == 0 { + continue + } + var field reflect.Value + if name == "" { + // use offset + if i == 1 { + useOffset = true + } else if !useOffset { + panic("can't mix named and unnamed subexpressions") + } + field = reflect.ValueOf(target).Elem().Field(i - 1) + } else { + // use name + if i == 1 { + useOffset = false + } else if useOffset { + panic("can't mix named and unnamed subexpressions") + } + field = reflect.ValueOf(target).Elem().FieldByName(name) + } + if field.Kind() == reflect.String { + field.SetString(m[i]) + } else if field.Kind() == reflect.Int { + v, err := strconv.Atoi(m[i]) + PanicOnErr(err) + field.SetInt(int64(v)) + } else if field.Kind() == reflect.Uint8 { + if len(m[i]) != 1 { + panic(fmt.Sprintf("expecting 1 char, got: %s", m[i])) + } + field.SetUint(uint64(m[i][0])) + } else { + panic(fmt.Sprintf("unknown kind: %s", field.Kind())) + } + } + return true +} + +func MustParseToStruct(re *regexp.Regexp, input string, target interface{}) { + if !ParseToStruct(re, input, target) { + panic(fmt.Errorf("failed to parse: %s", input)) + } +} + +func CharToLower(c byte) byte { + return strings.ToLower(string(c))[0] +} + +func CharToUpper(c byte) byte { + return strings.ToUpper(string(c))[0] +} + +func Contains(haystack []string, needle string) bool { + for _, s := range haystack { + if s == needle { + return true + } + } + return false +} + +func Abs[T constraints.Signed](x T) T { + if x < 0 { + return -x + } + return x +} + +func Gcd(x, y int) int { + if x <= 0 || y <= 0 { + panic(fmt.Errorf("invalid input: %d, %d", x, y)) + } + if x == y { + return x + } + if x > y { + return Gcd(x-y, y) + } else { + return Gcd(x, y-x) + } +} + +func Sign[T constraints.Signed](x T) int { + if x < 0 { + return -1 + } else if x > 0 { + return 1 + } else { + return 0 + } +}