Compare commits
55 Commits
change-inp
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| fb896a8d20 | |||
| 5bebd71c4e | |||
| 6d24500c69 | |||
| d17308873e | |||
| c6150871a3 | |||
| ec4a4243ca | |||
| 64de63ddbe | |||
| a17153662e | |||
| 852a805114 | |||
| 574fdf38a4 | |||
| a879d3bb88 | |||
| f48bae3bc3 | |||
| 745d95771c | |||
| c9df0e8fb8 | |||
| a692b4da4b | |||
| 62d8af2d1b | |||
| c159403427 | |||
| d900defb9b | |||
| 7ec430c8b5 | |||
| 255f39620e | |||
| 75ec54c0d2 | |||
| 32a84c2f3c | |||
| 2778e38f8b | |||
| 8a2afac023 | |||
| c16d3362fd | |||
| ad945bd41e | |||
| a2b9dfbcbe | |||
| 8c6d00683e | |||
| be12e11f5e | |||
| 4b51738c60 | |||
| 6946c978c6 | |||
| 3fc767f046 | |||
| 35dc086519 | |||
| 7686ffd788 | |||
| 96b4441bfc | |||
| 36b2f6feb3 | |||
| 8871be0bc9 | |||
| 76da133e30 | |||
| 7a8c20acc6 | |||
| c45c84ba8b | |||
| d11426e518 | |||
| 1c2e835ebc | |||
| a609bf72a9 | |||
| 8c6b9b3dfe | |||
| 9925c227a4 | |||
| e5c255d759 | |||
| 1ca62d7dbc | |||
| e4f381df4b | |||
| 923e0331f7 | |||
| 7c156be7a1 | |||
| a4ee3fde16 | |||
| 8a91af0713 | |||
| 7a92f12c01 | |||
| 5ad191354c | |||
| d386fc7d10 |
7
.github/workflows/build.yml
vendored
7
.github/workflows/build.yml
vendored
@ -1,5 +1,8 @@
|
||||
name: Build
|
||||
on: [push]
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "^test$"
|
||||
jobs:
|
||||
gobuild:
|
||||
runs-on: ubuntu-latest
|
||||
@ -14,6 +17,8 @@ jobs:
|
||||
run: go build -v ./day01/*.go
|
||||
- name: Build day two
|
||||
run: go build -v ./day02/*.go
|
||||
- name: Run day one
|
||||
run: go run -v ./day01/*.go
|
||||
- name: Display Go version
|
||||
run: go version
|
||||
- name: List files in the repository
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -22,3 +22,4 @@ go.work
|
||||
|
||||
# Problem data
|
||||
input*.txt
|
||||
inputs/
|
||||
|
||||
16
README.md
Normal file
16
README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Advent of Code 2023
|
||||
|
||||
An attempt to start programming again.
|
||||
|
||||
- [Day 1](./day01/trebuchet.go)
|
||||
- [Day 2](./day02/lottacubes.go)
|
||||
- [Day 3](./day03/engine-schema.go)
|
||||
- [Day 4](./day04/scratchcards.go)
|
||||
- [Day 5](./day05/seeds.go)
|
||||
- [Day 6](./day06/race.go)
|
||||
- [Day 7](./day07/cards.go)
|
||||
- [Day 8](./day08/charpath.go)
|
||||
- [Day 9](./day09/oasis.go)
|
||||
|
||||
|
||||
This repo gets automatically mirrored to [Github](https://github.com/Doddophonique/aoc2023).
|
||||
24
UNLICENSE
Normal file
24
UNLICENSE
Normal file
@ -0,0 +1,24 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
1000
day01/input
1000
day01/input
File diff suppressed because it is too large
Load Diff
1
day01/inputs
Symbolic link
1
day01/inputs
Symbolic link
@ -0,0 +1 @@
|
||||
../inputs
|
||||
@ -109,7 +109,7 @@ func CombineIndexes(s string) int {
|
||||
}
|
||||
|
||||
func main() {
|
||||
file, err := os.Open("input")
|
||||
file, err := os.Open("./inputs/day01_input")
|
||||
check(err)
|
||||
defer file.Close()
|
||||
|
||||
|
||||
100
day02/input
100
day02/input
@ -1,100 +0,0 @@
|
||||
Game 1: 4 red, 1 green, 15 blue; 6 green, 2 red, 10 blue; 7 blue, 6 green, 4 red; 12 blue, 10 green, 3 red
|
||||
Game 2: 3 green, 18 blue; 14 green, 4 red, 2 blue; 3 red, 14 green, 15 blue
|
||||
Game 3: 12 green, 2 blue; 9 green; 1 red, 11 blue, 4 green
|
||||
Game 4: 4 blue, 8 green, 5 red; 6 red, 7 blue, 9 green; 2 green, 2 red, 2 blue; 2 green, 6 blue, 9 red; 10 red, 9 green
|
||||
Game 5: 12 red, 1 green, 7 blue; 13 red, 16 blue; 16 blue, 10 red; 4 blue; 16 blue, 7 red; 1 blue, 7 red
|
||||
Game 6: 17 blue, 2 red; 5 blue, 6 green, 2 red; 5 green, 5 blue; 5 green, 12 blue, 4 red
|
||||
Game 7: 2 red, 1 blue, 10 green; 8 red, 14 green, 9 blue; 15 red, 1 blue, 6 green; 9 blue, 3 green, 10 red; 7 blue, 13 red, 4 green
|
||||
Game 8: 1 green, 2 blue; 7 red, 2 blue, 1 green; 1 red, 2 green; 4 red, 1 blue; 11 red, 2 green, 2 blue; 1 blue, 2 green, 11 red
|
||||
Game 9: 11 green, 11 blue, 6 red; 2 green, 3 blue, 2 red; 2 red, 11 blue, 14 green; 5 green, 7 red, 7 blue; 7 green, 1 red, 12 blue; 1 red, 8 green, 7 blue
|
||||
Game 10: 2 red, 8 green, 7 blue; 10 red, 5 green, 2 blue; 4 red, 8 green, 16 blue; 10 blue, 3 green, 15 red
|
||||
Game 11: 2 blue, 2 green, 5 red; 1 green, 3 red, 3 blue; 11 green, 1 red, 2 blue
|
||||
Game 12: 8 blue, 11 green, 14 red; 10 green, 13 red, 2 blue; 1 red, 6 green, 4 blue; 13 red, 11 green, 6 blue
|
||||
Game 13: 15 red, 17 green, 1 blue; 12 red, 1 blue, 1 green; 2 red, 1 blue, 14 green
|
||||
Game 14: 6 green, 11 red, 3 blue; 6 green, 2 blue; 2 green, 10 red, 8 blue; 2 red; 1 green, 9 red; 3 blue, 1 green, 3 red
|
||||
Game 15: 11 blue, 11 green, 4 red; 3 green, 10 blue; 2 red, 9 green, 9 blue
|
||||
Game 16: 2 blue, 11 green; 1 red, 1 blue, 11 green; 12 green, 1 blue, 1 red; 3 blue, 14 green, 1 red; 14 green, 4 blue; 2 blue, 12 green
|
||||
Game 17: 1 red, 2 blue, 4 green; 4 blue, 3 green; 1 green, 1 red, 6 blue; 1 red, 7 blue; 2 green
|
||||
Game 18: 3 red, 3 blue, 7 green; 2 blue, 2 red, 2 green; 4 red, 12 green; 5 green, 2 blue, 4 red; 3 red
|
||||
Game 19: 15 red, 7 blue, 10 green; 5 green, 8 red; 9 green, 8 red; 5 red, 10 green
|
||||
Game 20: 15 blue, 6 green, 11 red; 13 red, 9 blue, 1 green; 15 blue, 10 red, 11 green
|
||||
Game 21: 15 red, 4 green; 11 red, 2 blue, 4 green; 5 blue, 2 green, 4 red; 4 red, 5 blue; 6 red, 3 blue, 1 green
|
||||
Game 22: 4 green, 4 red, 13 blue; 3 red, 7 blue, 9 green; 12 blue, 13 green, 5 red
|
||||
Game 23: 20 green, 4 red; 6 blue, 9 red, 7 green; 6 green
|
||||
Game 24: 1 green, 3 blue, 6 red; 1 green, 1 blue, 2 red; 3 blue, 5 red, 1 green
|
||||
Game 25: 2 red, 9 blue, 2 green; 2 green, 1 red, 5 blue; 3 red, 1 green, 3 blue; 8 blue, 2 green, 3 red; 12 blue, 3 red; 1 blue, 2 green, 1 red
|
||||
Game 26: 2 blue, 5 green, 20 red; 2 blue, 6 red, 9 green; 3 red, 2 blue, 5 green
|
||||
Game 27: 17 blue, 2 red, 14 green; 15 green, 16 blue, 2 red; 13 blue, 13 green; 1 red, 7 green, 3 blue; 1 blue, 2 green
|
||||
Game 28: 5 blue, 6 red, 3 green; 7 red, 19 green; 11 blue, 13 green
|
||||
Game 29: 1 blue, 8 red, 7 green; 1 green, 1 red; 8 red, 7 green, 1 blue; 7 green, 2 red; 1 blue, 7 red; 1 blue, 2 red, 5 green
|
||||
Game 30: 3 red, 17 blue; 11 red, 3 blue, 8 green; 7 green, 12 blue, 10 red; 5 blue, 2 green
|
||||
Game 31: 14 blue, 7 green; 12 green, 14 blue, 2 red; 17 blue, 2 red, 8 green; 2 red, 3 blue, 11 green; 9 green, 4 blue; 1 red, 3 green, 1 blue
|
||||
Game 32: 15 red, 1 blue, 10 green; 15 green, 10 red, 1 blue; 2 red, 6 green, 1 blue
|
||||
Game 33: 10 green, 1 red, 16 blue; 11 blue, 14 green, 3 red; 14 green, 13 blue; 17 blue, 2 red, 3 green
|
||||
Game 34: 8 red, 7 blue, 8 green; 3 green, 1 red; 1 red, 1 green, 5 blue; 6 red, 8 green, 2 blue; 7 red, 8 blue, 3 green
|
||||
Game 35: 5 blue, 19 red; 2 blue, 11 red, 1 green; 16 red, 10 blue; 7 green, 3 blue, 6 red; 3 green, 18 red, 5 blue; 8 blue, 5 red
|
||||
Game 36: 9 red, 6 green, 10 blue; 9 red, 15 green, 6 blue; 6 red, 1 blue, 14 green
|
||||
Game 37: 7 green, 8 red, 2 blue; 3 blue, 5 red, 16 green; 1 green, 1 red, 3 blue
|
||||
Game 38: 5 green, 5 red, 3 blue; 10 blue, 19 red, 9 green; 2 red, 3 blue, 11 green
|
||||
Game 39: 15 red, 11 blue, 5 green; 11 green, 2 red, 6 blue; 2 blue, 3 green, 6 red; 15 red, 3 blue, 13 green
|
||||
Game 40: 7 green, 4 red, 1 blue; 6 blue, 6 green, 2 red; 2 blue, 3 red, 1 green; 1 blue, 3 red, 3 green; 2 red, 5 green, 3 blue
|
||||
Game 41: 10 blue, 8 green, 9 red; 7 blue, 9 red, 2 green; 10 blue, 4 red, 5 green
|
||||
Game 42: 8 blue, 13 green, 14 red; 8 blue, 1 green, 11 red; 4 red, 6 green, 3 blue; 14 green, 4 red, 2 blue
|
||||
Game 43: 2 red, 10 green, 19 blue; 5 blue, 4 green, 9 red; 9 green, 9 red, 2 blue
|
||||
Game 44: 6 red, 2 green, 3 blue; 2 blue, 12 red, 6 green; 1 red, 10 blue; 12 red, 6 green, 2 blue; 14 red, 13 green, 3 blue; 10 green, 9 blue, 11 red
|
||||
Game 45: 2 blue, 1 red, 1 green; 1 green, 1 blue; 2 green, 2 blue
|
||||
Game 46: 7 green, 1 red; 1 green, 4 blue, 1 red; 3 blue, 4 green, 1 red; 1 red, 4 green; 1 blue, 12 green, 1 red; 16 green, 1 blue
|
||||
Game 47: 4 blue, 8 green, 3 red; 6 red, 1 green, 3 blue; 16 green, 4 blue, 1 red; 4 blue, 8 red
|
||||
Game 48: 1 blue, 9 red, 8 green; 8 green, 2 blue, 6 red; 2 green; 4 blue, 5 red; 1 blue, 9 red, 9 green; 1 red, 1 blue, 3 green
|
||||
Game 49: 3 green, 2 blue; 7 blue, 4 red; 20 green, 5 red, 13 blue; 20 green, 1 red, 6 blue
|
||||
Game 50: 3 red, 3 green; 3 green, 3 red; 2 blue, 10 red; 3 blue, 5 green; 14 red, 2 green, 2 blue; 7 red, 2 green
|
||||
Game 51: 3 green, 3 blue, 2 red; 4 green, 16 red, 3 blue; 1 blue, 3 red; 9 red, 1 blue, 4 green
|
||||
Game 52: 6 red, 18 green, 7 blue; 2 blue, 1 red, 5 green; 8 blue, 6 red, 1 green; 1 red, 1 blue; 6 red, 3 green, 10 blue
|
||||
Game 53: 1 blue, 10 red, 3 green; 13 red, 2 green, 1 blue; 1 green, 2 red
|
||||
Game 54: 4 blue, 6 green, 2 red; 5 blue, 6 red, 2 green; 6 blue, 4 green, 8 red; 13 red, 10 blue, 1 green; 5 red, 5 green, 9 blue
|
||||
Game 55: 4 green, 18 red, 4 blue; 9 blue, 7 green, 16 red; 5 red, 6 blue, 14 green; 13 green, 11 red, 9 blue; 6 blue, 13 green, 1 red; 10 blue, 12 red, 14 green
|
||||
Game 56: 8 green, 5 blue, 10 red; 10 green, 7 red, 12 blue; 11 red, 12 blue, 1 green; 4 blue, 6 red, 10 green; 17 blue, 8 green, 2 red
|
||||
Game 57: 1 green, 2 red; 2 green, 5 red, 1 blue; 13 red, 3 green, 4 blue; 3 blue, 13 red, 9 green
|
||||
Game 58: 1 red, 7 blue, 4 green; 2 green, 1 blue, 1 red; 1 green, 11 blue; 12 blue; 1 blue, 5 green, 1 red; 3 green, 11 blue, 1 red
|
||||
Game 59: 5 green, 3 blue, 17 red; 2 red, 9 green; 1 blue, 4 green
|
||||
Game 60: 5 red, 5 green, 1 blue; 2 red, 2 blue, 6 green; 2 red, 3 blue, 3 green
|
||||
Game 61: 2 green, 3 blue, 4 red; 17 green, 1 blue; 1 green, 6 red, 4 blue; 3 blue, 9 green, 3 red; 18 green, 7 red, 2 blue
|
||||
Game 62: 5 red; 3 blue, 9 green; 3 red, 13 blue, 10 green; 14 green, 1 red, 2 blue; 7 blue, 13 green
|
||||
Game 63: 12 blue, 5 green; 5 green, 1 red, 1 blue; 4 red, 7 green, 9 blue; 8 blue, 2 green, 7 red
|
||||
Game 64: 3 blue, 11 green; 5 blue, 2 red, 5 green; 17 green, 5 blue, 1 red; 4 red, 3 blue, 4 green
|
||||
Game 65: 2 red, 1 blue, 2 green; 7 green, 2 red, 1 blue; 2 blue, 7 green, 1 red; 3 blue, 8 green, 3 red
|
||||
Game 66: 4 red, 12 blue, 1 green; 20 blue, 3 green, 2 red; 11 blue, 1 green
|
||||
Game 67: 12 blue, 10 red, 13 green; 19 green, 4 red, 7 blue; 12 red, 9 blue, 13 green
|
||||
Game 68: 2 blue, 17 green; 12 green, 2 red; 5 red, 2 green, 4 blue; 4 blue
|
||||
Game 69: 17 blue, 3 red, 1 green; 4 green, 8 blue, 8 red; 4 green, 7 red, 1 blue; 8 red, 1 green, 11 blue; 13 blue, 10 red, 9 green; 14 blue, 5 green, 6 red
|
||||
Game 70: 1 red, 2 blue, 4 green; 13 blue, 3 red, 2 green; 6 green, 8 blue
|
||||
Game 71: 5 red, 7 green, 1 blue; 11 green, 4 red, 1 blue; 1 red, 12 green, 10 blue; 1 red, 7 blue, 12 green
|
||||
Game 72: 9 blue, 4 green, 1 red; 6 green, 4 blue; 8 green, 5 blue, 1 red
|
||||
Game 73: 1 blue, 10 green, 14 red; 4 green; 2 blue, 9 red, 4 green; 2 blue, 13 green; 13 green, 13 red; 7 red, 5 green, 2 blue
|
||||
Game 74: 3 red, 1 blue, 3 green; 4 green, 1 blue, 1 red; 2 blue, 10 green, 1 red; 1 blue, 3 red, 1 green
|
||||
Game 75: 1 red, 1 blue, 1 green; 2 red, 1 green, 4 blue; 2 red, 4 blue; 1 blue, 1 red
|
||||
Game 76: 4 green, 2 blue, 6 red; 7 green, 1 red; 8 green, 4 red
|
||||
Game 77: 8 green, 7 blue, 5 red; 6 red, 14 green, 7 blue; 8 green, 7 blue; 1 red, 8 green, 8 blue
|
||||
Game 78: 6 red, 3 blue, 3 green; 7 blue, 10 red; 5 green, 10 blue, 1 red; 3 green, 11 blue, 4 red; 14 red, 9 blue, 2 green; 16 red, 2 green, 12 blue
|
||||
Game 79: 1 green; 5 green; 11 green, 3 blue, 2 red; 3 blue
|
||||
Game 80: 2 green, 2 red; 1 blue, 1 green, 1 red; 1 blue, 1 green, 2 red; 2 red; 5 green
|
||||
Game 81: 10 blue, 2 red, 9 green; 4 red, 12 blue, 5 green; 7 green, 4 blue, 6 red; 1 red, 13 green, 14 blue; 13 green, 11 blue
|
||||
Game 82: 4 blue, 2 green; 7 blue, 3 green, 5 red; 1 red, 4 blue, 3 green; 5 blue, 1 red, 6 green; 6 green, 4 red; 11 blue, 3 red, 5 green
|
||||
Game 83: 12 green; 5 red, 8 green; 11 red, 14 green, 1 blue; 9 green, 4 red
|
||||
Game 84: 5 blue, 1 red; 16 blue, 5 green; 1 red, 9 blue, 3 green; 11 blue; 1 green, 2 blue; 1 red, 7 blue, 4 green
|
||||
Game 85: 17 red, 5 blue; 18 blue, 2 red, 2 green; 18 blue, 2 green, 8 red
|
||||
Game 86: 4 red, 1 blue, 11 green; 6 blue, 7 green, 1 red; 3 green, 4 blue; 2 red, 7 blue, 2 green
|
||||
Game 87: 4 red, 5 blue; 1 green, 15 red, 1 blue; 11 blue, 12 red
|
||||
Game 88: 11 green, 3 red, 1 blue; 6 green, 1 blue, 1 red; 1 blue, 3 green; 2 blue, 4 green, 2 red
|
||||
Game 89: 2 green; 1 red, 2 green, 3 blue; 4 blue, 1 red, 10 green; 4 blue, 5 green; 6 blue, 1 red, 10 green
|
||||
Game 90: 15 red, 7 green, 17 blue; 7 blue, 1 red; 7 green, 6 red, 3 blue
|
||||
Game 91: 2 blue, 17 red, 6 green; 1 green, 1 blue, 6 red; 6 red, 4 blue; 10 green, 14 red, 1 blue; 7 blue, 10 green, 10 red; 16 red, 11 green, 9 blue
|
||||
Game 92: 1 green, 8 blue, 4 red; 4 green, 4 red, 4 blue; 1 green, 7 red, 4 blue
|
||||
Game 93: 11 blue, 12 red, 1 green; 9 blue, 2 green, 5 red; 7 red, 5 blue, 2 green
|
||||
Game 94: 7 blue, 10 green; 9 green, 9 blue, 2 red; 1 red, 5 green, 4 blue
|
||||
Game 95: 1 green, 1 blue, 2 red; 6 red; 1 blue; 1 green, 1 blue, 6 red
|
||||
Game 96: 1 blue, 1 red, 2 green; 4 red, 13 green, 1 blue; 1 blue, 13 green, 5 red; 7 green, 4 red
|
||||
Game 97: 10 blue, 5 red, 5 green; 4 red, 8 green, 2 blue; 5 red, 2 green, 15 blue; 2 red, 1 green, 4 blue; 2 red, 14 blue; 14 blue, 4 green
|
||||
Game 98: 11 red, 8 green, 9 blue; 3 blue, 1 green, 14 red; 10 blue, 2 red, 4 green; 7 blue, 11 red, 3 green; 5 red, 12 blue, 4 green; 7 green, 7 blue, 8 red
|
||||
Game 99: 3 green, 2 blue, 1 red; 15 red, 8 blue, 7 green; 18 red, 12 blue, 2 green
|
||||
Game 100: 11 red, 1 blue, 2 green; 3 red, 3 green; 1 blue, 8 red, 4 green; 5 green, 5 blue, 1 red; 2 green, 1 red, 6 blue; 2 green, 8 red, 1 blue
|
||||
1
day02/inputs
Symbolic link
1
day02/inputs
Symbolic link
@ -0,0 +1 @@
|
||||
../inputs
|
||||
@ -140,7 +140,7 @@ func PrintAndWait[T any](x T) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
file, err := os.Open("input")
|
||||
file, err := os.Open("./inputs/day02_input")
|
||||
check(err)
|
||||
defer file.Close()
|
||||
|
||||
|
||||
220
day03/engine-schema.go
Normal file
220
day03/engine-schema.go
Normal file
@ -0,0 +1,220 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
// "strings"
|
||||
"bufio"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func check(e error) {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
func PrintAndWait(x ...any) {
|
||||
fmt.Print(x)
|
||||
fmt.Scanln()
|
||||
}
|
||||
|
||||
func MatchNumbers(lines []string, index int, ast []int, total *int) {
|
||||
// Regex that finds the numbers in a row
|
||||
renum := regexp.MustCompile("[0-9]+")
|
||||
// Gather numbers in prev line
|
||||
prevLine := renum.FindAllStringIndex(lines[index-1], -1)
|
||||
// Gather numbers in this line
|
||||
thisLine := renum.FindAllStringIndex(lines[index], -1)
|
||||
// Gather numbers in next line
|
||||
nextLine := renum.FindAllStringIndex(lines[index+1], -1)
|
||||
// Calculate the number of numbers in three lines
|
||||
totalNumbers := len(prevLine) + len(thisLine) + len(nextLine)
|
||||
|
||||
// Now we create a big array with all the indexes
|
||||
allIndexes := prevLine
|
||||
for i := range thisLine {
|
||||
allIndexes = append(allIndexes, thisLine[i])
|
||||
}
|
||||
for i := range nextLine {
|
||||
allIndexes = append(allIndexes, nextLine[i])
|
||||
}
|
||||
|
||||
// Now we create a big array with all the numbers
|
||||
// We start from the previous line
|
||||
allNumbers := renum.FindAllString(lines[index-1], -1)
|
||||
thisNums := renum.FindAllString(lines[index], -1)
|
||||
for i := range thisNums {
|
||||
allNumbers = append(allNumbers, thisNums[i])
|
||||
}
|
||||
nextNums := renum.FindAllString(lines[index+1], -1)
|
||||
for i := range nextNums {
|
||||
allNumbers = append(allNumbers, nextNums[i])
|
||||
}
|
||||
// When we start, we have zero matches
|
||||
matches := 0
|
||||
// We will stop when we encounter two numbers
|
||||
twoNums := [2]int{0, 0}
|
||||
_ = twoNums
|
||||
// Cycling through all numbers, but stopping at two matches
|
||||
for i := 0; i < totalNumbers && matches < 2; i++ {
|
||||
if (ast[0] >= allIndexes[i][0] - 1 && ast[0] <= allIndexes[i][1]) {
|
||||
matches += 1
|
||||
num, _ := strconv.Atoi(allNumbers[i])
|
||||
twoNums[matches - 1] = num
|
||||
}
|
||||
}
|
||||
if(matches == 2) {
|
||||
tempGears := twoNums[0] * twoNums[1]
|
||||
*total += tempGears
|
||||
}
|
||||
}
|
||||
|
||||
func CheckGears(lines []string) {
|
||||
total := 0
|
||||
totalPoint := &total
|
||||
// Regex that finds the numbers in a row
|
||||
//renum := regexp.MustCompile("[0-9]+")
|
||||
// Regex that finds the asterisks in a row
|
||||
resym := regexp.MustCompile("[*]")
|
||||
// For every line starting from the second
|
||||
for i := 0; i < len(lines) - 1; i++ {
|
||||
// Take the index of the asterisks
|
||||
asteriskIndex := resym.FindAllStringIndex(lines[i], - 1)
|
||||
// For every index we get
|
||||
for j := range asteriskIndex {
|
||||
MatchNumbers(lines, i, asteriskIndex[j], totalPoint)
|
||||
}
|
||||
}
|
||||
// firstLineNums := renum.FindAllStringIndex(lines[index], -1)
|
||||
// firstLineSymbolsIndex := resym.FindAllStringIndex(lines[index], -1)
|
||||
// secondLineSymbolsIndex := resym.FindAllStringIndex(lines[index + 1], -1)
|
||||
// For every *number index range*, check if in the same line there is a
|
||||
// symbol on (first - 1) or (last + 1), check in other lines if there is
|
||||
// a symbol in a specific interval of numbers. If you find a match, you
|
||||
// can break as you just need one symbol
|
||||
fmt.Printf("Total of gears is: %d\n", total)
|
||||
}
|
||||
|
||||
func main() {
|
||||
file, err := os.Open("./inputs/day03_input")
|
||||
check(err)
|
||||
defer file.Close()
|
||||
|
||||
// This regex find the numbers inside strings
|
||||
renum := regexp.MustCompile("[0-9]+")
|
||||
resym := regexp.MustCompile("[^0-9.]+")
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
var lines []string
|
||||
var totalSum int = 0
|
||||
|
||||
// Read the whole file into an array of strings
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, scanner.Text())
|
||||
}
|
||||
numLines := len(lines)
|
||||
numbers := make([][]int, numLines)
|
||||
|
||||
// The 2D array of numbers will hold all the numbers to easily
|
||||
// match them with corresponding strings in the file using the index
|
||||
// For every line in the file, create an array of numbers
|
||||
for i := 0; i < numLines; i++ {
|
||||
tempNums := renum.FindAllString(lines[i], -1)
|
||||
for j := 0; j < len(tempNums); j++ {
|
||||
num, _ := strconv.Atoi(tempNums[j])
|
||||
numbers[i] = append(numbers[i], num)
|
||||
}
|
||||
}
|
||||
/* Line [0] needs to check only line 1 for symbols.
|
||||
Similarly, the last line needs to check only
|
||||
(last line index - 1) for symbols.
|
||||
So we first check the line [0], then start a loop
|
||||
from 1 to (last line index - 1)
|
||||
*/
|
||||
firstLineNums := renum.FindAllStringIndex(lines[0], -1)
|
||||
firstLineSymbolsIndex := resym.FindAllStringIndex(lines[0], -1)
|
||||
secondLineSymbolsIndex := resym.FindAllStringIndex(lines[1], -1)
|
||||
// For every *number index range*, check if in the same line there is a
|
||||
// symbol on (first - 1) or (last + 1), check in other lines if there is
|
||||
// a symbol in a specific interval of numbers. If you find a match, you
|
||||
// can break as you just need one symbol
|
||||
for i := range firstLineNums {
|
||||
for j := range firstLineSymbolsIndex {
|
||||
if firstLineSymbolsIndex[j][0] >= firstLineNums[i][0] - 1 &&
|
||||
(firstLineSymbolsIndex[j][0] <= firstLineNums[i][1]) {
|
||||
totalSum += numbers[0][i]
|
||||
break
|
||||
}
|
||||
}
|
||||
for j := range secondLineSymbolsIndex {
|
||||
if (secondLineSymbolsIndex[j][0] >= firstLineNums[i][0] - 1) &&
|
||||
(secondLineSymbolsIndex[j][0] <= firstLineNums[i][1]) {
|
||||
totalSum += numbers[0][i]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
// Now we loop from 1 to (last index - i)
|
||||
for i := 1; i < len(lines) - 1; i++ {
|
||||
// We need to check the current line against an interval of three lines
|
||||
// breaking the loop for a single number as soon as we find a match
|
||||
// (we don't want duplicate matches)
|
||||
currentLineNums := renum.FindAllStringIndex(lines[i], -1)
|
||||
previousLineIndex := resym.FindAllStringIndex(lines[i - 1], -1)
|
||||
currentLineIndex := resym.FindAllStringIndex(lines[i], -1)
|
||||
nextLineIndex := resym.FindAllStringIndex(lines[i + 1], -1)
|
||||
OuterLoop:
|
||||
for k := range currentLineNums {
|
||||
for j := range previousLineIndex {
|
||||
if previousLineIndex[j][0] >= currentLineNums[k][0] - 1 &&
|
||||
previousLineIndex[j][0] <= currentLineNums[k][1] {
|
||||
totalSum += numbers[i][k]
|
||||
continue OuterLoop
|
||||
}
|
||||
}
|
||||
for j := range currentLineIndex {
|
||||
if currentLineIndex[j][0] >= currentLineNums[k][0] - 1 &&
|
||||
currentLineIndex[j][0] <= currentLineNums[k][1] {
|
||||
totalSum += numbers[i][k]
|
||||
continue OuterLoop
|
||||
}
|
||||
}
|
||||
for j := range nextLineIndex {
|
||||
if nextLineIndex[j][0] >= currentLineNums[k][0] - 1 &&
|
||||
nextLineIndex[j][0] <= currentLineNums[k][1] {
|
||||
totalSum += numbers[i][k]
|
||||
continue OuterLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Now we need to loop the last line and confront it with previous
|
||||
// and itself
|
||||
lastLineNums := renum.FindAllStringIndex(lines[len(lines) - 1], -1)
|
||||
lastLineSymbolsIndex := resym.FindAllStringIndex(lines[len(lines) - 1], -1)
|
||||
notLastLineSymbolsIndex := resym.FindAllStringIndex(lines[len(lines) - 2], -1)
|
||||
// For every *number index range*, check if in the same line there is a
|
||||
// symbol on (last - 1) or (last + 1), check in other lines if there is
|
||||
// a symbol in a specific interval of numbers. If you find a match, you
|
||||
// can break as you just need one symbol
|
||||
for i := range lastLineNums {
|
||||
for j := range lastLineSymbolsIndex {
|
||||
if lastLineSymbolsIndex[j][0] >= lastLineNums[i][0] - 1 &&
|
||||
(lastLineSymbolsIndex[j][0] <= lastLineNums[i][1]) {
|
||||
totalSum += numbers[len(lines) - 1][i]
|
||||
break
|
||||
}
|
||||
}
|
||||
for j := range notLastLineSymbolsIndex {
|
||||
if (notLastLineSymbolsIndex[j][0] >= lastLineNums[i][0] - 1) &&
|
||||
(notLastLineSymbolsIndex[j][0] <= lastLineNums[i][1]) {
|
||||
totalSum += numbers[len(lines) - 1][i]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Printf("The total sum is: %d\n", totalSum)
|
||||
CheckGears(lines)
|
||||
}
|
||||
1
day03/inputs
Symbolic link
1
day03/inputs
Symbolic link
@ -0,0 +1 @@
|
||||
../inputs
|
||||
1
day04/inputs
Symbolic link
1
day04/inputs
Symbolic link
@ -0,0 +1 @@
|
||||
../inputs
|
||||
115
day04/scratchcards.go
Normal file
115
day04/scratchcards.go
Normal file
@ -0,0 +1,115 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"bufio"
|
||||
"os"
|
||||
// "strconv"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func check(e error) {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
func PrintAndWait(x ...any) {
|
||||
fmt.Print(x)
|
||||
fmt.Scanln()
|
||||
}
|
||||
|
||||
func SplitSets(s []string) ([]string, []string) {
|
||||
|
||||
// Split the two sets into winning and my numbers
|
||||
tempwinningNumbers := s[0]
|
||||
tempMyNumbers := s[1]
|
||||
// Regex to populate a string with numbers
|
||||
renum := regexp.MustCompile("[0-9]+")
|
||||
myNumbers := renum.FindAllString(tempMyNumbers, -1)
|
||||
winningNumbers := renum.FindAllString(tempwinningNumbers, -1)
|
||||
|
||||
return myNumbers, winningNumbers
|
||||
}
|
||||
|
||||
func FindMatches(myNum []string, winNum []string) int {
|
||||
matches := 0
|
||||
for i := range myNum {
|
||||
for j := range winNum {
|
||||
if (myNum[i] == winNum[j]) {
|
||||
matches += 1
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return matches
|
||||
}
|
||||
|
||||
func CalcTickets(s []string, index int, tpr []int ) {
|
||||
|
||||
myNumbers, winningNumbers := SplitSets(s)
|
||||
matches := FindMatches(myNumbers, winningNumbers)
|
||||
if (matches > 0) {
|
||||
for j := 0; j < tpr[index]; j++ {
|
||||
for i := index; i < index + matches; i++ {
|
||||
tpr[i+1] += 1
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func CalcScore (s []string, t *int) {
|
||||
|
||||
myNumbers, winningNumbers := SplitSets(s)
|
||||
matches := FindMatches(myNumbers, winningNumbers)
|
||||
if(matches > 0) {
|
||||
tempTotal := 1
|
||||
for i := 0; i < matches - 1; i++ {
|
||||
tempTotal *= 2
|
||||
}
|
||||
*t += tempTotal
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
file, err := os.Open("./inputs/day04_input")
|
||||
check(err)
|
||||
defer file.Close()
|
||||
|
||||
// The total is a simple sum
|
||||
var total int = 0
|
||||
var totalPoint *int = &total
|
||||
// To keep track of the amount of tickets, an array as long
|
||||
// as the number of lines
|
||||
var lines []string
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, scanner.Text())
|
||||
}
|
||||
ticketsPerRow := make([]int, len(lines))
|
||||
tprPoint := ticketsPerRow[0:len(lines)]
|
||||
|
||||
for i := range ticketsPerRow {
|
||||
ticketsPerRow[i] = 1
|
||||
}
|
||||
|
||||
// Scan every line
|
||||
for i := 0; i < len(lines); i++ {
|
||||
// e.g.: Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
|
||||
cardAndNumbers := strings.Split(lines[i], ":")
|
||||
// At this point, cardAndNumbers has "Card N"
|
||||
// We don't need this information (yet?)
|
||||
allNumbers := strings.Split(cardAndNumbers[1], "|")
|
||||
CalcScore(allNumbers, totalPoint)
|
||||
CalcTickets(allNumbers, i, tprPoint)
|
||||
}
|
||||
|
||||
numTickets := 0
|
||||
for i := range ticketsPerRow {
|
||||
numTickets += ticketsPerRow[i]
|
||||
}
|
||||
fmt.Printf("The scratchcards are worth %d points.\n", total)
|
||||
fmt.Printf("In total, I have %d scratchcards.", numTickets)
|
||||
}
|
||||
1
day05/inputs
Symbolic link
1
day05/inputs
Symbolic link
@ -0,0 +1 @@
|
||||
../inputs
|
||||
158
day05/seeds.go
Normal file
158
day05/seeds.go
Normal file
@ -0,0 +1,158 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
// "strings"
|
||||
"bufio"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"regexp"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Minimum struct {
|
||||
mu sync.Mutex
|
||||
minimum int
|
||||
}
|
||||
func check(e error) {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
func PrintAndWait(x ...any) {
|
||||
fmt.Print(x...)
|
||||
fmt.Scanln()
|
||||
}
|
||||
|
||||
func GetMaps(scanner *bufio.Scanner, re *regexp.Regexp) [][]int {
|
||||
// Scan until there is an empty line
|
||||
var tempNums int = 0
|
||||
tempArray := make([][]int, 0)
|
||||
for i := 0; scanner.Scan() && scanner.Text() != ""; i++ {
|
||||
tempString := re.FindAllString(scanner.Text(), -1)
|
||||
temp := make([]int, 0)
|
||||
for j := range tempString {
|
||||
tempNums, _ = strconv.Atoi(tempString[j])
|
||||
temp = append(temp, tempNums)
|
||||
}
|
||||
tempArray = append(tempArray, temp)
|
||||
}
|
||||
// Prepare for next line
|
||||
scanner.Scan()
|
||||
return tempArray
|
||||
}
|
||||
|
||||
func (min *Minimum) ParallelMinimum(start, finish int, atrocity [][][]int, wg *sync.WaitGroup) {
|
||||
// We check the array one by one, need a temp array because
|
||||
// SeedToLocation wants it
|
||||
tempNum := make([]int, 1)
|
||||
tempMin := []int{0}
|
||||
_ = tempMin
|
||||
for i := 0; i < finish; i++ {
|
||||
tempNum[0] = start + i
|
||||
tempMin := SeedToLocation(tempNum, atrocity)
|
||||
// Need to modify a shared variable, lock
|
||||
min.mu.Lock()
|
||||
if tempMin[0] < min.minimum {
|
||||
min.minimum = tempMin[0]
|
||||
}
|
||||
min.mu.Unlock()
|
||||
}
|
||||
// We finished with the Goroutine
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
func SeedToLocation(seeds []int, atrocity [][][]int) []int {
|
||||
tempRes := seeds
|
||||
for i := range atrocity {
|
||||
tempRes = NextResource(tempRes, atrocity[i])
|
||||
}
|
||||
return tempRes
|
||||
}
|
||||
|
||||
func NextResource(previous []int, resource [][]int) []int {
|
||||
tempRes := make([]int, 0)
|
||||
// [0] is dest, [1] is source, [2] is range
|
||||
for i := range previous {
|
||||
for j := range resource {
|
||||
if previous[i] >= resource[j][1] &&
|
||||
previous[i] <= (resource[j][1] + resource[j][2] - 1) {
|
||||
tempRes = append(tempRes, previous[i] + (resource[j][0] - resource[j][1]))
|
||||
}
|
||||
}
|
||||
// If we didn't add an element to the array
|
||||
if len(tempRes) == i {
|
||||
tempRes = append(tempRes, previous[i])
|
||||
}
|
||||
}
|
||||
return tempRes
|
||||
}
|
||||
func main () {
|
||||
file, err := os.Open("./inputs/day05_input")
|
||||
check(err)
|
||||
defer file.Close()
|
||||
|
||||
min := Minimum{
|
||||
minimum: math.MaxInt,
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Regex that finds the numbers in a row
|
||||
renum := regexp.MustCompile("[0-9]+")
|
||||
|
||||
var seeds []int
|
||||
var soils, fertilizers, waters, lights, temperatures,
|
||||
humidities, locations [][]int
|
||||
scanner := bufio.NewScanner(file)
|
||||
// We know that the seeds only have one row
|
||||
scanner.Scan()
|
||||
// Put all the numbers in an array of strings
|
||||
seedsNums := renum.FindAllString(scanner.Text(), -1)
|
||||
// Extract every number from the string
|
||||
for i := 0; i < len(seedsNums); i++ {
|
||||
num, _ := strconv.Atoi(seedsNums[i])
|
||||
seeds = append(seeds, num)
|
||||
}
|
||||
// We know we have an empty string and just a title, skip them
|
||||
scanner.Scan()
|
||||
scanner.Scan()
|
||||
// Should be possible to just pass the scanner
|
||||
soils = GetMaps(scanner, renum)
|
||||
fertilizers = GetMaps(scanner, renum)
|
||||
waters = GetMaps(scanner, renum)
|
||||
lights = GetMaps(scanner, renum)
|
||||
temperatures = GetMaps(scanner, renum)
|
||||
humidities = GetMaps(scanner, renum)
|
||||
locations = GetMaps(scanner, renum)
|
||||
|
||||
tempRes := make([]int, 0)
|
||||
// Actually insane behaviour
|
||||
monster := [][][]int{
|
||||
soils, fertilizers, waters,
|
||||
lights, temperatures, humidities,
|
||||
locations,
|
||||
}
|
||||
// Send the seeds, receive
|
||||
tempRes = SeedToLocation(seeds, monster)
|
||||
|
||||
minimum := math.MaxInt
|
||||
for i := range tempRes {
|
||||
if tempRes[i] < minimum {
|
||||
minimum = tempRes[i]
|
||||
}
|
||||
}
|
||||
fmt.Printf("Minimum of first part: %d\n", minimum)
|
||||
|
||||
// Actual madness
|
||||
for i := 0; i < len(seeds); i += 2 {
|
||||
wg.Add(1)
|
||||
go min.ParallelMinimum(seeds[i], seeds[i+1], monster, &wg)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
//tempRes = SeedToLocation(allSeeds, monster)
|
||||
fmt.Printf("Minimum of second part: %d\n", min.minimum)
|
||||
}
|
||||
1
day06/inputs
Symbolic link
1
day06/inputs
Symbolic link
@ -0,0 +1 @@
|
||||
../inputs
|
||||
126
day06/race.go
Normal file
126
day06/race.go
Normal file
@ -0,0 +1,126 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
// "strings"
|
||||
"bufio"
|
||||
// "math"
|
||||
"os"
|
||||
"strconv"
|
||||
"regexp"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Race struct {
|
||||
mu sync.Mutex
|
||||
total int
|
||||
}
|
||||
|
||||
func (r *Race) WeRaceBoys(time, distance int, wg *sync.WaitGroup) {
|
||||
// As we just need to find the minimum necessary and then subtract it from
|
||||
// the maximum, probably a good idea starting form the middle
|
||||
tempTime := 0
|
||||
for i := int(time/2); i > 0; i-- {
|
||||
tempDist := i * (time - i)
|
||||
if tempDist <= distance {
|
||||
tempTime = i + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
// If the minimum is tempTime, then the maximum is time - tempTime
|
||||
// time - 2*tempTime is the number of possible victories
|
||||
r.mu.Lock()
|
||||
r.total *= (time - (2 * tempTime - 1))
|
||||
r.mu.Unlock()
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
func MultRaceDist(time, dist []string) ([]int, []int){
|
||||
tempT, tempD := make([]int, 0), make([]int, 0)
|
||||
for i := range time {
|
||||
num, _ := strconv.Atoi(time[i])
|
||||
tempT = append(tempT, num)
|
||||
num, _ = strconv.Atoi(dist[i])
|
||||
tempD = append(tempD, num)
|
||||
}
|
||||
return tempT, tempD
|
||||
}
|
||||
|
||||
func SingleRaceDist(time, dist []string) (int, int) {
|
||||
strT, strD := "", ""
|
||||
numT, numD := 0, 0
|
||||
// Create two big strings
|
||||
for i := range time {
|
||||
strT += time[i]
|
||||
strD += dist[i]
|
||||
}
|
||||
|
||||
numT, _ = strconv.Atoi(strT)
|
||||
numD, _ = strconv.Atoi(strD)
|
||||
|
||||
return numT, numD
|
||||
}
|
||||
|
||||
func check(e error) {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
func PrintAndWait(x ...any) {
|
||||
fmt.Print(x...)
|
||||
fmt.Scanln()
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
file, err := os.Open("./inputs/day06_input")
|
||||
check(err)
|
||||
defer file.Close()
|
||||
|
||||
// Struct for multiple races
|
||||
rMult := Race{
|
||||
total: 1,
|
||||
}
|
||||
// Struct for a single race
|
||||
rSing := Race{
|
||||
total: 1,
|
||||
}
|
||||
_ = &rSing
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Regex that finds the numbers in a row
|
||||
renum := regexp.MustCompile("[0-9]+")
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
time, distance := make([]int, 0), make([]int, 0)
|
||||
tempStrings := make([]string, 0)
|
||||
// Generic, would work for more rows
|
||||
for scanner.Scan() {
|
||||
tempStrings = append(tempStrings, scanner.Text())
|
||||
}
|
||||
// Now populate time and distance
|
||||
timeStr := renum.FindAllString(tempStrings[0], - 1)
|
||||
distStr := renum.FindAllString(tempStrings[1], - 1)
|
||||
|
||||
time, distance = MultRaceDist(timeStr, distStr)
|
||||
|
||||
// E.g.: if I hold the button for 1ms and then release it, it will travel at
|
||||
// 1mm/ms fo the remaining amount of seconds.
|
||||
// We can skip the holding down 0 and tMAX ms.
|
||||
// Once we find the MIN amount of ms necessary to win, the limit is
|
||||
// MAX - MIN
|
||||
wg.Add(len(time))
|
||||
for i := 0; i < len(time); i++ {
|
||||
go rMult.WeRaceBoys(time[i], distance[i], &wg)
|
||||
}
|
||||
|
||||
// Silly implementation of the single race
|
||||
singT, singD := SingleRaceDist(timeStr, distStr)
|
||||
wg.Add(1)
|
||||
go rSing.WeRaceBoys(singT, singD, &wg)
|
||||
|
||||
wg.Wait()
|
||||
fmt.Printf("Multiple races result: %d.\n", rMult.total)
|
||||
fmt.Printf("Single race result: %d.\n", rSing.total)
|
||||
}
|
||||
366
day07/cards.go
Normal file
366
day07/cards.go
Normal file
@ -0,0 +1,366 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var mapSeedsFirst = map[string]int{
|
||||
"A": 12,
|
||||
"K": 11,
|
||||
"Q": 10,
|
||||
"J": 9,
|
||||
"T": 8,
|
||||
"9": 7,
|
||||
"8": 6,
|
||||
"7": 5,
|
||||
"6": 4,
|
||||
"5": 3,
|
||||
"4": 2,
|
||||
"3": 1,
|
||||
"2": 0,
|
||||
}
|
||||
|
||||
var mapSeedsSecond = map[string]int{
|
||||
"A": 12,
|
||||
"K": 11,
|
||||
"Q": 10,
|
||||
"T": 9,
|
||||
"9": 8,
|
||||
"8": 7,
|
||||
"7": 6,
|
||||
"6": 5,
|
||||
"5": 4,
|
||||
"4": 3,
|
||||
"3": 2,
|
||||
"2": 1,
|
||||
"J": 0,
|
||||
}
|
||||
|
||||
type Game struct {
|
||||
mu sync.Mutex
|
||||
ranks []int
|
||||
// 0: High card, 1: One pair, 2: Two pair, 3: Three of a kind
|
||||
// 4: Full house, 5: Four of a kind, 6: Five of a kind
|
||||
typeOfHand [7][]string
|
||||
indexOfHand [7][]int
|
||||
baseThirteen [7][]int
|
||||
}
|
||||
|
||||
func (g *Game) ChangeBase(hType, index int, mapSeeds map[string]int, wg *sync.WaitGroup) {
|
||||
// Starting from the first char [0], we create the base13 num
|
||||
chars := len(g.typeOfHand[hType][index])
|
||||
baseTN := g.typeOfHand[hType][index]
|
||||
decNum := 0
|
||||
for i := 0; i < chars; i++ {
|
||||
// This should be refactored to be a bit more legible
|
||||
// It just computes N * 13^i and adds it over
|
||||
decNum += int(float64(mapSeeds[string(baseTN[i])]) * math.Pow(13, float64(chars-i)))
|
||||
}
|
||||
g.baseThirteen[hType][index] = decNum
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
func (g *Game) AnalyzeMap(cards string, index, mapSize, offset int) {
|
||||
// The offset defaults to 0 for the regular game
|
||||
// it is +1 for a game with Jokers\
|
||||
mapSeed := mapSeedsFirst
|
||||
if offset != 0 {
|
||||
mapSeed = mapSeedsSecond
|
||||
}
|
||||
switch mapSize {
|
||||
// Five of a kind
|
||||
case 1:
|
||||
g.mu.Lock()
|
||||
g.typeOfHand[6] = append(g.typeOfHand[6], cards)
|
||||
g.indexOfHand[6] = append(g.indexOfHand[6], index)
|
||||
g.mu.Unlock()
|
||||
// Four of a kind || Full House
|
||||
case 2:
|
||||
i := FullOrFour(cards, offset, mapSeed)
|
||||
g.mu.Lock()
|
||||
g.typeOfHand[i] = append(g.typeOfHand[i], cards)
|
||||
g.indexOfHand[i] = append(g.indexOfHand[i], index)
|
||||
g.mu.Unlock()
|
||||
// Three of a kind || Two pair
|
||||
case 3:
|
||||
i := ThreeOrTwo(cards, offset, mapSeed)
|
||||
g.mu.Lock()
|
||||
g.typeOfHand[i] = append(g.typeOfHand[i], cards)
|
||||
g.indexOfHand[i] = append(g.indexOfHand[i], index)
|
||||
g.mu.Unlock()
|
||||
// One pair
|
||||
case 4:
|
||||
g.mu.Lock()
|
||||
g.typeOfHand[1] = append(g.typeOfHand[1], cards)
|
||||
g.indexOfHand[1] = append(g.indexOfHand[1], index)
|
||||
g.mu.Unlock()
|
||||
// High card
|
||||
case 5:
|
||||
g.mu.Lock()
|
||||
g.typeOfHand[0] = append(g.typeOfHand[0], cards)
|
||||
g.indexOfHand[0] = append(g.indexOfHand[0], index)
|
||||
g.mu.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Game) DetermineType(cards string, index int, wg *sync.WaitGroup) {
|
||||
// We create a map and we check the length. Depending on the length, we
|
||||
// insert the string in a specific type
|
||||
m := make(map[string]int)
|
||||
for i := 0; i < len(cards); i++ {
|
||||
key := string(cards[i])
|
||||
m[key] = mapSeedsFirst[key]
|
||||
}
|
||||
// Now, depending on the number of elements in the map, we can assign
|
||||
// append cards to a specific rank
|
||||
mapSize := len(m)
|
||||
g.AnalyzeMap(cards, index, mapSize, 0)
|
||||
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
func (g *Game) SecondGame(cards string, index int, wg *sync.WaitGroup) {
|
||||
// If I don't have Js, run the standard DetermineType
|
||||
m := make(map[string]int)
|
||||
n := make(map[string]int)
|
||||
for i := 0; i < len(cards); i++ {
|
||||
key := string(cards[i])
|
||||
// We need to track the number of Js
|
||||
m[key] += 1
|
||||
// This is to track the type of hand, knowing the number of Js
|
||||
n[key] = mapSeedsSecond[key]
|
||||
}
|
||||
mapSize := len(n)
|
||||
switch m["J"] {
|
||||
case 0:
|
||||
// We have a hand without Js
|
||||
wg.Add(1)
|
||||
g.DetermineType(cards, index, wg)
|
||||
case 1:
|
||||
// If there is a J, J can be use is not adding information, therefore -1
|
||||
g.AnalyzeMap(cards, index, (mapSize - 1), 1)
|
||||
case 2:
|
||||
g.AnalyzeMap(cards, index, (mapSize - 1), 2)
|
||||
case 3:
|
||||
g.AnalyzeMap(cards, index, (mapSize - 1), 3)
|
||||
case 4:
|
||||
g.AnalyzeMap(cards, index, (mapSize - 1), 4)
|
||||
case 5:
|
||||
wg.Add(1)
|
||||
g.DetermineType(cards, index, wg)
|
||||
}
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
func ThreeOrTwo(cards string, offset int, mapSeed map[string]int) int {
|
||||
m := make(map[string]int)
|
||||
for i := 0; i < len(cards); i++ {
|
||||
key := string(cards[i])
|
||||
m[key] += 1
|
||||
}
|
||||
// If we are in the second game, remove J
|
||||
if mapSeed["J"] == 0 {
|
||||
m["J"] = 0
|
||||
}
|
||||
// m[i] returns 0 if the element is not in the map. I take advantage
|
||||
// of that
|
||||
tempNum := 0
|
||||
for i := range mapSeed {
|
||||
if m[i] > tempNum {
|
||||
tempNum = m[i]
|
||||
}
|
||||
}
|
||||
// If an element has 3 values, we have a three of a kind
|
||||
if tempNum+offset == 3 {
|
||||
return 3
|
||||
/// If an element has 2 values, we have a two pair
|
||||
} else if tempNum+offset == 2 {
|
||||
return 2
|
||||
}
|
||||
PrintAndWait("This has run for ", cards)
|
||||
return -1
|
||||
}
|
||||
func FullOrFour(cards string, offset int, mapSeed map[string]int) int {
|
||||
m := make(map[string]int)
|
||||
for i := 0; i < len(cards); i++ {
|
||||
key := string(cards[i])
|
||||
m[key] += 1
|
||||
}
|
||||
// If we are in the second game, remove J
|
||||
if mapSeed["J"] == 0 {
|
||||
m["J"] = 0
|
||||
}
|
||||
// m[i] returns 0 if the element is not in the map. I take advantage
|
||||
// of that
|
||||
// Better to save the maximum number
|
||||
tempNum := 0
|
||||
for i := range mapSeed {
|
||||
if m[i] > tempNum {
|
||||
tempNum = m[i]
|
||||
}
|
||||
}
|
||||
// If an element has four values, we have a Four of a kind
|
||||
if tempNum+offset == 4 {
|
||||
return 5
|
||||
/// If an element has 3 values, we have a Full House
|
||||
} else if tempNum+offset == 3 {
|
||||
return 4
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func check(e error) {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
func PrintAndWait(x ...any) {
|
||||
fmt.Print(x...)
|
||||
fmt.Scanln()
|
||||
}
|
||||
|
||||
// https://www.golangprograms.com/golang-program-for-implementation-of-quick-sort.html
|
||||
// I need to learn how this shing works
|
||||
func quicksort(a, h []int, hType int) []int {
|
||||
if len(a) < 2 {
|
||||
return a
|
||||
}
|
||||
|
||||
left, right := 0, len(a)-1
|
||||
|
||||
pivot := 0
|
||||
|
||||
a[pivot], a[right] = a[right], a[pivot]
|
||||
h[pivot], h[right] = h[right], h[pivot]
|
||||
|
||||
for i, _ := range a {
|
||||
if a[i] < a[right] {
|
||||
a[left], a[i] = a[i], a[left]
|
||||
h[left], h[i] = h[i], h[left]
|
||||
left++
|
||||
}
|
||||
}
|
||||
|
||||
a[left], a[right] = a[right], a[left]
|
||||
h[left], h[right] = h[right], h[left]
|
||||
|
||||
quicksort(a[:left], h[:left], hType)
|
||||
quicksort(a[left+1:], h[left+1:], hType)
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
file, err := os.Open("./inputs/day07_input")
|
||||
check(err)
|
||||
defer file.Close()
|
||||
|
||||
// Struct for regular game
|
||||
g := Game{}
|
||||
// Struct for the Joker game
|
||||
jo := Game{}
|
||||
|
||||
// Variable where we store every line in the file
|
||||
lines := make([]string, 0)
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, scanner.Text())
|
||||
}
|
||||
// Array of strings, set of cards
|
||||
var cards []string
|
||||
// Array of int, bet
|
||||
var bet []int
|
||||
// Now, split the lines
|
||||
for i := 0; i < len(lines); i++ {
|
||||
tempString := strings.Split(lines[i], " ")
|
||||
cards = append(cards, tempString[0])
|
||||
tempNum, _ := strconv.Atoi(tempString[1])
|
||||
bet = append(bet, tempNum)
|
||||
}
|
||||
// Rank will be from 1 to len(lines)
|
||||
g.ranks = make([]int, len(lines))
|
||||
jo.ranks = make([]int, len(lines))
|
||||
// What do we know for sure? 5 identical seeds are the highest ranks,
|
||||
// 5 completely different seeds are the lowest ranks.
|
||||
// We can iterate for every set of cards, and do different things
|
||||
// if the map we build has one element, five elements or the worst
|
||||
// case (two, three or four elements).
|
||||
//
|
||||
// Two identical: 4oK or FH
|
||||
// Three identical: 3oK or 22
|
||||
// Four identical: 12
|
||||
//
|
||||
// With this, I put every typeOfHand in a different array
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(2 * len(lines))
|
||||
for i := 0; i < len(lines); i++ {
|
||||
g.DetermineType(cards[i], i, &wg)
|
||||
jo.SecondGame(cards[i], i, &wg)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
// Now that g.typeOfHand has every type of hand separated, the rank
|
||||
// is determined by the first card(s). I can convert every number
|
||||
// to a base 13 representation and sort.
|
||||
// In g.indexOfHand I have the index of the corresponding type.
|
||||
|
||||
// For every type of hand
|
||||
for i := range g.typeOfHand {
|
||||
// As many wait groups as the element we will iterate
|
||||
wg.Add(len(g.typeOfHand[i]))
|
||||
wg.Add(len(jo.typeOfHand[i]))
|
||||
// We also need to initialize the array g.baseThirteen so we can
|
||||
// keep the same index
|
||||
g.baseThirteen[i] = make([]int, len(g.typeOfHand[i]))
|
||||
jo.baseThirteen[i] = make([]int, len(jo.typeOfHand[i]))
|
||||
// For every element in a single type of hand
|
||||
for j := range g.typeOfHand[i] {
|
||||
g.ChangeBase(i, j, mapSeedsFirst, &wg)
|
||||
}
|
||||
for j := range jo.typeOfHand[i] {
|
||||
jo.ChangeBase(i, j, mapSeedsSecond, &wg)
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
// A sort of some kind. Important is to also move the index with the number as
|
||||
// well.
|
||||
for i := range g.baseThirteen {
|
||||
quicksort(g.baseThirteen[i], g.indexOfHand[i], i)
|
||||
quicksort(jo.baseThirteen[i], jo.indexOfHand[i], i)
|
||||
}
|
||||
|
||||
curRank := 1
|
||||
rank := 0
|
||||
// Iter every array
|
||||
for i := range g.typeOfHand {
|
||||
for j := range g.typeOfHand[i] {
|
||||
index := g.indexOfHand[i][j]
|
||||
rank += curRank * bet[index]
|
||||
curRank++
|
||||
}
|
||||
}
|
||||
fmt.Printf("Rank: %d\n", rank)
|
||||
|
||||
curRank = 1
|
||||
rank = 0
|
||||
// Iter every array
|
||||
for i := range jo.typeOfHand {
|
||||
for j := range jo.typeOfHand[i] {
|
||||
index := jo.indexOfHand[i][j]
|
||||
rank += curRank * bet[index]
|
||||
curRank++
|
||||
}
|
||||
}
|
||||
fmt.Printf("Rank: %d\n", rank)
|
||||
|
||||
}
|
||||
1
day07/inputs
Symbolic link
1
day07/inputs
Symbolic link
@ -0,0 +1 @@
|
||||
../inputs
|
||||
233
day08/charpath.go
Normal file
233
day08/charpath.go
Normal file
@ -0,0 +1,233 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
"regexp"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const LEFT = 'L'
|
||||
|
||||
type Nodes struct {
|
||||
mu sync.Mutex
|
||||
commands []int32
|
||||
singleN []int32
|
||||
leftN []int32
|
||||
rightN []int32
|
||||
index int
|
||||
steps uint64
|
||||
allSteps []int
|
||||
}
|
||||
|
||||
func check(e error) {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
func PrintAndWait(x ...any) {
|
||||
fmt.Print(x...)
|
||||
fmt.Scanln()
|
||||
}
|
||||
|
||||
// https://siongui.github.io/2017/06/03/go-find-lcm-by-gcd/
|
||||
// greatest common divisor (GCD) via Euclidean algorithm
|
||||
func GCD(a, b int) int {
|
||||
for b != 0 {
|
||||
t := b
|
||||
b = a % b
|
||||
a = t
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// find Least Common Multiple (LCM) via GCD
|
||||
func LCM(a, b int, integers ...int) int {
|
||||
result := a * b / GCD(a, b)
|
||||
|
||||
for i := 0; i < len(integers); i++ {
|
||||
result = LCM(result, integers[i])
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (n *Nodes) toByteSingle(s string) {
|
||||
// I've just received something like AAA
|
||||
var temp int32
|
||||
for i := len(s) - 1; i >= 0; i-- {
|
||||
a := int32(s[i])
|
||||
temp += a << ((len(s) - 1 - i) * 8)
|
||||
}
|
||||
n.singleN = append(n.singleN, temp)
|
||||
}
|
||||
|
||||
func (n *Nodes) toByteDuet(s, r string) {
|
||||
// I've just received something like AAA BBB
|
||||
var tempL, tempR int32
|
||||
for i := len(s) - 1; i >= 0; i-- {
|
||||
tempL += int32(s[i]) << ((len(s) - 1 - i) * 8)
|
||||
tempR += int32(r[i]) << ((len(s) - 1 - i) * 8)
|
||||
}
|
||||
n.leftN = append(n.leftN, tempL)
|
||||
n.rightN = append(n.rightN, tempR)
|
||||
}
|
||||
|
||||
func (n *Nodes) findNext(myN int32) int {
|
||||
//var wg sync.WaitGroup
|
||||
ind := 0
|
||||
for i := 0; i < len(n.singleN); i++ {
|
||||
if myN^n.singleN[i] == 0 {
|
||||
n.mu.Lock()
|
||||
n.index = i
|
||||
n.mu.Unlock()
|
||||
ind = i
|
||||
break
|
||||
}
|
||||
}
|
||||
return ind
|
||||
}
|
||||
|
||||
func (n *Nodes) findAll(ind int, sp []int, wg *sync.WaitGroup) {
|
||||
index := 0
|
||||
// We only go from the start
|
||||
matching := n.rightN[sp[ind]]
|
||||
if n.commands[0]^LEFT == 0 {
|
||||
matching = n.leftN[sp[ind]]
|
||||
}
|
||||
index = n.findNext(matching)
|
||||
n.allSteps[ind]++
|
||||
i := 0
|
||||
for {
|
||||
// Every step is in a single direction. For every step, we may need to
|
||||
// scan len(n.singleN) elements.
|
||||
// Circular loop
|
||||
index = n.findNext(matching)
|
||||
// Increment i after finding the match
|
||||
i++
|
||||
i = i % len(n.commands)
|
||||
// By default, we will assume we are on the right
|
||||
matching = n.rightN[index]
|
||||
//PrintAndWait()
|
||||
// If we are not, we are in the left
|
||||
if n.commands[i]^LEFT == 0 {
|
||||
matching = n.leftN[index]
|
||||
}
|
||||
n.allSteps[ind]++
|
||||
// If we find XXZ, end
|
||||
temp := matching & 255
|
||||
if temp ^ 'Z' == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
//fmt.Printf("I started from %d, matched at %d, taking %d steps.\n", sp[ind], index, n.allSteps[ind] )
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
func timer(name string) func() {
|
||||
start := time.Now()
|
||||
return func() {
|
||||
fmt.Printf("%s took %v\n", name, time.Since(start))
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
defer timer ("main")()
|
||||
file, err := os.Open("./inputs/day08_input")
|
||||
check(err)
|
||||
defer file.Close()
|
||||
// Struct with my node
|
||||
n := Nodes{}
|
||||
// Prepare the regex
|
||||
repath := regexp.MustCompile("([A-Z]{3})")
|
||||
// Build the END
|
||||
var END = 'Z'
|
||||
END += ('Z' << 8)
|
||||
END += ('Z' << 16)
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
scanner.Scan()
|
||||
// First line, RL commands
|
||||
strCommands := scanner.Text()
|
||||
// Get every char inside the string just obtained
|
||||
for i := 0; i < len(strCommands); i++ {
|
||||
n.commands = append(n.commands, int32(strCommands[i]))
|
||||
}
|
||||
// One empty line
|
||||
scanner.Scan()
|
||||
// X = (Y, Z)
|
||||
// We regex this one
|
||||
for scanner.Scan() {
|
||||
tempNodes := repath.FindAllString(scanner.Text(), -1)
|
||||
n.toByteSingle(tempNodes[0])
|
||||
n.toByteDuet(tempNodes[1], tempNodes[2])
|
||||
}
|
||||
// We start from 0, we find the match
|
||||
// Let's start an infinite loop
|
||||
// Circular index
|
||||
i := 0
|
||||
// We start from the AAA element
|
||||
START := 'A'
|
||||
START += ('A' << 8)
|
||||
START += ('A' << 16)
|
||||
matching := START
|
||||
// Store where AAA is
|
||||
n.findNext(matching)
|
||||
// By default, we will assume we are on the right
|
||||
// If we are not, we are in the left
|
||||
matching = n.rightN[n.index]
|
||||
if n.commands[i]^LEFT == 0 {
|
||||
matching = n.leftN[n.index]
|
||||
}
|
||||
n.steps++
|
||||
// Infinite loop
|
||||
for {
|
||||
// Every step is in a single direction. For every step, we may need to
|
||||
// scan len(n.singleN) elements.
|
||||
// Circular loop
|
||||
n.findNext(matching)
|
||||
// Increment i after finding the match
|
||||
i++
|
||||
i = i % len(n.commands)
|
||||
// By default, we will assume we are on the right
|
||||
matching = n.rightN[n.index]
|
||||
//PrintAndWait()
|
||||
// If we are not, we are in the left
|
||||
if n.commands[i]^LEFT == 0 {
|
||||
matching = n.leftN[n.index]
|
||||
}
|
||||
n.steps++
|
||||
// If we find ZZZ, end
|
||||
if matching^END == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fmt.Printf("\nSteps: %d\n", n.steps)
|
||||
// Now, for the main event
|
||||
// Let's get ready to rumble
|
||||
startPoints := make([]int, 0)
|
||||
for i := 0; i < len(n.singleN); i++ {
|
||||
// Lets remove all bytes except last 8
|
||||
temp := n.singleN[i] & 255
|
||||
if (temp ^ 'A') == 0 {
|
||||
startPoints = append(startPoints, i)
|
||||
}
|
||||
}
|
||||
// Now, from the starting points, we should go and match until
|
||||
// we find a path that ends in Z
|
||||
n.allSteps = make([]int, len(startPoints))
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < len(startPoints); i++ {
|
||||
wg.Add(1)
|
||||
go n.findAll(i, startPoints, &wg)
|
||||
}
|
||||
wg.Wait()
|
||||
result := 1
|
||||
for i := 0; i < len(n.allSteps); i++ {
|
||||
result = LCM(result, n.allSteps[i])
|
||||
}
|
||||
fmt.Printf("Steps: %d\n", result)
|
||||
}
|
||||
1
day08/inputs
Symbolic link
1
day08/inputs
Symbolic link
@ -0,0 +1 @@
|
||||
../inputs
|
||||
1
day09/inputs
Symbolic link
1
day09/inputs
Symbolic link
@ -0,0 +1 @@
|
||||
../inputs
|
||||
149
day09/oasis.go
Normal file
149
day09/oasis.go
Normal file
@ -0,0 +1,149 @@
|
||||
package main
|
||||
|
||||
import(
|
||||
"fmt"
|
||||
"os"
|
||||
"bufio"
|
||||
"sync"
|
||||
"time"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Parallel code, global vars
|
||||
type Series struct {
|
||||
mu sync.Mutex
|
||||
numStore [][]int
|
||||
total uint64
|
||||
}
|
||||
|
||||
func check(e error) {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
func PrintAndWait(x ...any) {
|
||||
fmt.Print(x...)
|
||||
fmt.Scanln()
|
||||
}
|
||||
// use defer timer("funcname")() when the function you want to
|
||||
// test starts
|
||||
func timer(name string) func() {
|
||||
start := time.Now()
|
||||
return func() {
|
||||
fmt.Printf("%s took %v\n", name, time.Since(start))
|
||||
}
|
||||
}
|
||||
|
||||
func PredictValueBack(numbers []int) []int {
|
||||
// Are we finished? By default, true
|
||||
temp := true
|
||||
for i := 0; i < len(numbers); i++ {
|
||||
if numbers[i] != 0 {
|
||||
temp = false
|
||||
break
|
||||
}
|
||||
}
|
||||
// Check to end recursion
|
||||
if temp == true {
|
||||
return numbers
|
||||
}
|
||||
|
||||
newNums := make([]int, len(numbers) - 1)
|
||||
for i := 0; i < len(numbers) - 1; i++ {
|
||||
newNums[i] = numbers[i + 1] - numbers[i]
|
||||
}
|
||||
myNums := PredictValueBack(newNums)
|
||||
addValue := newNums[0] - myNums[0]
|
||||
// We need to append at the start
|
||||
newNums = append([]int{addValue}, newNums...)
|
||||
return newNums
|
||||
}
|
||||
|
||||
func (ser *Series) CallPredictBack(numbers []int, wg *sync.WaitGroup) {
|
||||
tempNum := PredictValueBack(numbers)
|
||||
ser.mu.Lock()
|
||||
ser.total += uint64(numbers[0] - tempNum[0])
|
||||
ser.mu.Unlock()
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
func PredictValue(numbers []int) []int {
|
||||
// Are we finished? By default, true
|
||||
temp := true
|
||||
for i := 0; i < len(numbers); i++ {
|
||||
if numbers[i] != 0 {
|
||||
temp = false
|
||||
break
|
||||
}
|
||||
}
|
||||
// Check to end recursion
|
||||
if temp == true {
|
||||
return numbers
|
||||
}
|
||||
|
||||
newNums := make([]int, len(numbers) - 1)
|
||||
for i := 0; i < len(numbers) - 1; i++ {
|
||||
newNums[i] = numbers[i + 1] - numbers[i]
|
||||
}
|
||||
myNums := PredictValue(newNums)
|
||||
addValue := myNums[len(myNums) - 1]
|
||||
newNums = append(newNums, newNums[len(newNums) - 1] + addValue)
|
||||
return newNums
|
||||
}
|
||||
|
||||
func (ser *Series) CallPredict(numbers []int, wg *sync.WaitGroup) {
|
||||
tempNum := PredictValue(numbers)
|
||||
lt := len(tempNum) - 1
|
||||
ln := len(numbers) - 1
|
||||
ser.mu.Lock()
|
||||
ser.total += uint64(numbers[ln] + tempNum[lt])
|
||||
ser.mu.Unlock()
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
func main() {
|
||||
defer timer("main")()
|
||||
file, err := os.Open("./inputs/day09_input")
|
||||
check(err)
|
||||
defer file.Close()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
renum := regexp.MustCompile("(\\-[0-9]+|[0-9]+)")
|
||||
|
||||
ser := Series{ total: 0, }
|
||||
|
||||
lines := make([]string, 0)
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, scanner.Text())
|
||||
}
|
||||
ser.numStore = make([][]int, len(lines))
|
||||
for i := 0; i < len(lines); i++ {
|
||||
temp := renum.FindAllString(lines[i], -1)
|
||||
for j := 0; j < len(temp); j++ {
|
||||
num, err := strconv.Atoi(temp[j])
|
||||
check(err)
|
||||
ser.numStore[i] = append(ser.numStore[i], num)
|
||||
}
|
||||
}
|
||||
// Now I have a 2D array with all the numbers, I can start RECURSING
|
||||
wg.Add(len(ser.numStore))
|
||||
for i := 0; i < len(ser.numStore); i++ {
|
||||
go ser.CallPredict(ser.numStore[i], &wg)
|
||||
}
|
||||
wg.Wait()
|
||||
fmt.Printf("%d\n", ser.total)
|
||||
|
||||
ser.total = 0
|
||||
wg.Add(len(ser.numStore))
|
||||
for i := 0; i < len(ser.numStore); i++ {
|
||||
go ser.CallPredictBack(ser.numStore[i], &wg)
|
||||
}
|
||||
wg.Wait()
|
||||
fmt.Printf("%d\n", ser.total)
|
||||
|
||||
}
|
||||
1
day10/inputs
Symbolic link
1
day10/inputs
Symbolic link
@ -0,0 +1 @@
|
||||
../inputs
|
||||
48
day10/maze.go
Normal file
48
day10/maze.go
Normal file
@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Parallel code, global vars
|
||||
type Nodes struct {
|
||||
mu sync.Mutex
|
||||
variable int
|
||||
}
|
||||
|
||||
func check(e error) {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
func PrintAndWait(x ...any) {
|
||||
fmt.Print(x...)
|
||||
fmt.Scanln()
|
||||
}
|
||||
|
||||
// use defer timer("funcname")() when the function you want to
|
||||
// test starts
|
||||
func timer(name string) func() {
|
||||
start := time.Now()
|
||||
return func() {
|
||||
fmt.Printf("%s took %v\n", name, time.Since(start))
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
file, err := os.Open("./inputs")
|
||||
check(err)
|
||||
defer file.Close()
|
||||
|
||||
lines := make([]string, 0)
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, scanner.Text())
|
||||
}
|
||||
}
|
||||
42
template.go
Normal file
42
template.go
Normal file
@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import()
|
||||
|
||||
// Parallel code, global vars
|
||||
type Nodes struct {
|
||||
mu sync.Mutex
|
||||
variable type
|
||||
}
|
||||
|
||||
func check(e error) {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
}
|
||||
|
||||
func PrintAndWait(x ...any) {
|
||||
fmt.Print(x...)
|
||||
fmt.Scanln()
|
||||
}
|
||||
// use defer timer("funcname")() when the function you want to
|
||||
// test starts
|
||||
func timer(name string) func() {
|
||||
start := time.Now()
|
||||
return func() {
|
||||
fmt.Printf("%s took %v\n", name, time.Since(start))
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
file, err := os.Open("./inputs")
|
||||
check(err)
|
||||
defer file.Close()
|
||||
|
||||
lines := make([]string, 0)
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, scanner.Text())
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user