Compare commits

...

55 Commits

Author SHA1 Message Date
fb896a8d20 Starting day10 2023-12-12 19:17:01 +01:00
5bebd71c4e Day10 skeleton 2023-12-11 22:32:49 +01:00
6d24500c69 Update README.md 2023-12-10 22:17:51 +01:00
d17308873e Day 9, working part 1 and 2 2023-12-10 22:12:30 +01:00
c6150871a3 Added generic template for almost every day 2023-12-10 20:04:59 +01:00
ec4a4243ca Merge branch 'day08' 2023-12-10 19:55:59 +01:00
64de63ddbe Working d8p2 2023-12-10 00:46:26 +01:00
a17153662e Working d8p1 2023-12-09 23:00:54 +01:00
852a805114 Modified .gitignore to exclude input files 2023-12-09 14:13:27 +01:00
574fdf38a4 Non-working, archival purpose 2023-12-08 23:46:47 +01:00
a879d3bb88 Updated README.md 2023-12-08 13:14:18 +00:00
f48bae3bc3 Working day07, huge mess 2023-12-08 13:12:41 +00:00
745d95771c Working part 1, I forgot to properly sort an array 2023-12-08 07:57:17 +01:00
c9df0e8fb8 Added debug prints 2023-12-08 01:00:01 +01:00
a692b4da4b Removed one bug, many to go 2023-12-08 00:39:40 +01:00
62d8af2d1b Non-working prototype 2023-12-08 00:33:30 +01:00
c159403427 WIP: every type of hand has its array 2023-12-07 22:10:27 +01:00
d900defb9b Initial commit for day 7 2023-12-07 14:16:41 +00:00
7ec430c8b5 Updated README.md 2023-12-07 13:58:44 +00:00
255f39620e Working d6p2, multithreaded 2023-12-07 10:32:55 +00:00
75ec54c0d2 Working day6 part1 2023-12-07 00:30:24 +01:00
32a84c2f3c First draft of day 6 2023-12-06 22:52:25 +01:00
2778e38f8b Unoptimized and unhinged d5p2, parallel bruteforce 2023-12-06 22:05:18 +01:00
8a2afac023 Working d5p1, but I don't know what my code does 2023-12-06 20:00:08 +01:00
c16d3362fd Implemented function to gather the different items 2023-12-06 16:43:03 +00:00
ad945bd41e Early draft of day 5, archival 2023-12-05 23:20:45 +01:00
a2b9dfbcbe Merge branch 'day03' 2023-12-05 20:16:07 +01:00
8c6d00683e Working version of d3p2, code needs refactoring 2023-12-05 20:13:44 +01:00
be12e11f5e Non-working code, archival purpose 2023-12-04 23:54:13 +01:00
4b51738c60 Fix refactoring causing errors during compiling 2023-12-04 21:49:35 +01:00
6946c978c6 Merge branch 'day03' 2023-12-04 16:02:56 +00:00
3fc767f046 Starting to refactor day03 2023-12-04 15:29:27 +00:00
35dc086519 Updated README.md 2023-12-04 13:55:43 +00:00
7686ffd788 Merge branch 'day04' 2023-12-04 13:54:03 +00:00
96b4441bfc Merge branch 'day03' 2023-12-04 13:53:56 +00:00
36b2f6feb3 Optimized my code by 140300% just by doing things correctly 2023-12-04 13:49:18 +00:00
8871be0bc9 First draft of working part two, heavily unoptimized 2023-12-04 13:34:48 +00:00
76da133e30 Working first part of day04 2023-12-04 09:57:37 +00:00
7a8c20acc6 Merge branch 'day03' into day04 2023-12-04 08:49:24 +00:00
c45c84ba8b Merge branch 'change-inputs-folder' into day04 2023-12-04 08:44:37 +00:00
d11426e518 The worst code I've ever written, but somehow it works 2023-12-03 21:35:05 +01:00
1c2e835ebc Working code, terrible code, debug prints 2023-12-03 21:33:46 +01:00
a609bf72a9 Merge remote-tracking branch 'gitea/change-inputs-folder' 2023-12-03 18:53:33 +01:00
8c6b9b3dfe WIP of new approach 2023-12-03 16:52:32 +00:00
9925c227a4 Scrapping the current approach. Archival purpose 2023-12-03 16:10:23 +00:00
e5c255d759 Initial draft of day03, non-working, archival purpose 2023-12-03 13:24:33 +00:00
1ca62d7dbc Merge branch 'change-inputs-folder' into day03 2023-12-03 08:08:16 +00:00
e4f381df4b Added UNLICENSE file 2023-12-02 19:34:37 +01:00
923e0331f7 Merge branch 'gitea-actions' 2023-12-02 19:15:12 +01:00
7c156be7a1 Adding a tag to specify when to build 2023-12-02 19:14:16 +01:00
a4ee3fde16 Add README.md
All checks were successful
Build / gobuild (push) Successful in 56s
2023-12-02 19:08:52 +01:00
8a91af0713 Fixed a small oversight in folder structure 2023-12-02 16:59:44 +00:00
7a92f12c01 Truying to do something really silly with symlinks 2023-12-02 16:56:35 +00:00
5ad191354c Trying to run the code for day01 2023-12-02 16:50:46 +00:00
d386fc7d10 Changed folder structure 2023-12-02 16:49:56 +00:00
27 changed files with 1516 additions and 1103 deletions

View File

@ -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
View File

@ -22,3 +22,4 @@ go.work
# Problem data
input*.txt
inputs/

16
README.md Normal file
View 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
View 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/>

File diff suppressed because it is too large Load Diff

1
day01/inputs Symbolic link
View File

@ -0,0 +1 @@
../inputs

View File

@ -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()

View File

@ -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
View File

@ -0,0 +1 @@
../inputs

View File

@ -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
View 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
View File

@ -0,0 +1 @@
../inputs

1
day04/inputs Symbolic link
View File

@ -0,0 +1 @@
../inputs

115
day04/scratchcards.go Normal file
View 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
View File

@ -0,0 +1 @@
../inputs

158
day05/seeds.go Normal file
View 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
View File

@ -0,0 +1 @@
../inputs

126
day06/race.go Normal file
View 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
View 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
View File

@ -0,0 +1 @@
../inputs

233
day08/charpath.go Normal file
View 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
View File

@ -0,0 +1 @@
../inputs

1
day09/inputs Symbolic link
View File

@ -0,0 +1 @@
../inputs

149
day09/oasis.go Normal file
View 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
View File

@ -0,0 +1 @@
../inputs

48
day10/maze.go Normal file
View 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
View 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())
}
}