mirror of
https://github.com/fredrikr79/advent_of_code.git
synced 2026-04-23 18:26:11 +02:00
Compare commits
12 Commits
f495d64ba8
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 16684fea02 | |||
| 87457e0a92 | |||
| cf64d5950e | |||
| e5a214187a | |||
| 9d8676a109 | |||
| 3b5c6ae52d | |||
| 850cfecc67 | |||
| d4267d6f51 | |||
| b4013642be | |||
| 6225b525d1 | |||
| f78d3083ff | |||
| 7db243be05 |
@@ -0,0 +1,2 @@
|
||||
input.txt
|
||||
input
|
||||
@@ -0,0 +1,37 @@
|
||||
# aoc 2016/1
|
||||
&fras $ input.txt
|
||||
°/$"_, _" ⍜⇌↘₁
|
||||
≡◇⊃[⍥¯⊙i ⨂"LR"⊢|⋕↘1] # pre-process
|
||||
\(⊂⊢⊙⊣⊸⍜∩⊢×) # directions at each token
|
||||
⬚0/(+⊙/×) # move in direction
|
||||
+∩⌵°ℂ
|
||||
$Part₁
|
||||
# the idea is to represent our position
|
||||
# as a complex number (2d vector). rotate by
|
||||
# 90 or -90 degrees when you encounter L or R
|
||||
# by multiplying by i or -i on the direction
|
||||
# vector.
|
||||
# this can be done by folding with the initial
|
||||
# values i (direction) and 0 (position), pattern-
|
||||
# matching the next token on L or R and recognizing
|
||||
# them by ⍩.
|
||||
# once the direction vector has been rotated
|
||||
# accordingly, ⍥\+⋕ to add the direction unit vector
|
||||
# to the position vector n times for token Ln or Rn.
|
||||
#
|
||||
# we can see many awesome pieces of functional and
|
||||
# array oriented code!
|
||||
|
||||
&fras $ input.txt
|
||||
°/$"_, _" ⍜⇌↘₁
|
||||
∧◇(⍥(⊙⊂⟜⊣\+)⋕ ⍣(
|
||||
⍩⊙⍜⊢(×i) °(⊂@L)
|
||||
| ⍩⊙⍜⊢(ׯi) °(⊂@R))
|
||||
)⊙i_0⊙[]
|
||||
⌵+°ℂ ⊡⊸(⊢⍖=1⧆)⇌ ◌
|
||||
$Part₂
|
||||
# for this part, we only need to keep track of
|
||||
# each intermediate step (all our positions).
|
||||
# this by modifying the ⍥-loop to keep a log.
|
||||
# then we can find the first reoccurring position
|
||||
# using the new ⧆.
|
||||
@@ -0,0 +1,16 @@
|
||||
# aoc 2016/2
|
||||
&fras "input.txt"
|
||||
⍜⇌(▽⊸(>0\+≠@\n)) # world's most complicated right-trim
|
||||
# parse each letter of the puzzle input.
|
||||
# update position vector.
|
||||
⊂∧(
|
||||
⍣(⍩(-i) ◌°.@U
|
||||
| ⍩(+i) ◌°.@D
|
||||
| ⍩(-1) ◌°.@L
|
||||
| ⍩(+1) ◌°.@R
|
||||
| ⍩(⟜⊂) ◌°.@\n)
|
||||
⍜°ℂ∩(↥¯1↧1) # clamp vector
|
||||
)⊙0⊙[]
|
||||
⍉⊟°ℂ +ℂ1 1 # translate
|
||||
⌝⊥10 ⊡⊙(+1°△3_3) # grab code
|
||||
$Part₁
|
||||
@@ -0,0 +1 @@
|
||||
use flake
|
||||
@@ -0,0 +1,8 @@
|
||||
89010123
|
||||
78121874
|
||||
87430965
|
||||
96549874
|
||||
45678903
|
||||
32019012
|
||||
01329801
|
||||
10456732
|
||||
Generated
+27
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1755186698,
|
||||
"narHash": "sha256-wNO3+Ks2jZJ4nTHMuks+cxAiVBGNuEBXsT29Bz6HASo=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "fbcf476f790d8a217c3eab4e12033dc4a0f6d23c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
description = "advent of code 2024 day 10 in odin";
|
||||
|
||||
inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
|
||||
outputs =
|
||||
{ self, nixpkgs, ... }:
|
||||
let
|
||||
system = "x86_64-linux";
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
};
|
||||
in
|
||||
{
|
||||
devShells.${system}.default = pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
odin
|
||||
];
|
||||
shellHook = ''
|
||||
echo "Entering odin devshell..."
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package aoc2024day10
|
||||
|
||||
import "core:fmt"
|
||||
import "core:os"
|
||||
import "core:slice"
|
||||
import "core:strconv"
|
||||
import "core:strings"
|
||||
import "core:unicode"
|
||||
|
||||
EXAMPLE_INPUT_PATH :: "example.txt"
|
||||
PUZZLE_INPUT_PATH :: "input.txt"
|
||||
|
||||
Grid :: struct($T: typeid) {
|
||||
data: []T,
|
||||
width: int,
|
||||
height: int,
|
||||
}
|
||||
|
||||
gpos :: proc(i: int) -> (row: int, col: int) {
|
||||
return i / g.width, i % g.width
|
||||
}
|
||||
|
||||
gidx :: proc(row, col: int) -> (i: int) {
|
||||
return row * g.width + col
|
||||
}
|
||||
|
||||
gidx_safe :: proc(row, col: int) -> (m: Maybe(int)) {
|
||||
if !(0 <= row && row <= g.height && 0 <= col && col <= g.width) do return nil
|
||||
return gidx(row, col)
|
||||
}
|
||||
|
||||
gget :: proc(row, col: int) -> (value: int) {
|
||||
return g.data[gidx(row, col)]
|
||||
}
|
||||
|
||||
gget_safe :: proc(row, col: int) -> (mvalue: Maybe(any)) {
|
||||
if m := gidx_safe(row, col); m == nil do return nil
|
||||
else do return g.data[m.(int)]
|
||||
}
|
||||
|
||||
gset :: proc(row, col: int, value: $T) {
|
||||
g.data[gidx(row, col)] = value
|
||||
}
|
||||
|
||||
// TODO: use enumerated array
|
||||
gadj_idx :: proc(
|
||||
row, col: int,
|
||||
) -> (
|
||||
north: Maybe(int),
|
||||
east: Maybe(int),
|
||||
south: Maybe(int),
|
||||
west: Maybe(int),
|
||||
) {
|
||||
north = gidx_safe(row - 1, col)
|
||||
east = gidx_safe(row, col + 1)
|
||||
south = gidx_safe(row + 1, col)
|
||||
west = gidx_safe(row, col - 1)
|
||||
return
|
||||
}
|
||||
|
||||
g: Grid(int)
|
||||
|
||||
main :: proc() {
|
||||
path := len(os.args) == 2 ? os.args[1] : EXAMPLE_INPUT_PATH
|
||||
input := string(
|
||||
os.read_entire_file_from_filename(path) or_else panic("failed to read input file"),
|
||||
)
|
||||
|
||||
g = parse(input)
|
||||
fmt.println("part 1:", solve1())
|
||||
}
|
||||
|
||||
parse :: proc(input: string) -> Grid(int) {
|
||||
data: [dynamic]int
|
||||
width, height := 0, 0
|
||||
|
||||
for line in strings.split_lines(strings.trim_right_space(input)) {
|
||||
if width == 0 do width = len(line)
|
||||
for r in line {
|
||||
digit := strconv._digit_value(r)
|
||||
append(&data, digit)
|
||||
}
|
||||
height += 1
|
||||
}
|
||||
|
||||
return {data[:], width, height}
|
||||
}
|
||||
|
||||
solve1 :: proc() -> (res: int) {
|
||||
inner :: proc(row, col, cur: int) -> (score: int) {
|
||||
n, e, s, w := gadj_idx(row, col)
|
||||
dir: [4]Maybe(int) = {n, e, s, w}
|
||||
directions: []int = slice.mapper(
|
||||
slice.filter(dir[:], proc(m: Maybe(int)) -> bool {return m != nil}),
|
||||
proc(m: Maybe(int)) -> int {return m.(int)},
|
||||
)
|
||||
heights: []int = slice.mapper(directions, proc(i: int) -> int {return gget(gpos(i))})
|
||||
fmt.println(dir, directions, heights)
|
||||
cache[gidx(row, col)] = score
|
||||
return
|
||||
}
|
||||
|
||||
@(static) cache: map[int]int
|
||||
return inner(0, 2, 0)
|
||||
}
|
||||
|
||||
Test :: struct {
|
||||
hello: int,
|
||||
method: proc(_: int) -> int,
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
7 6 4 2 1
|
||||
1 2 7 8 9
|
||||
9 7 6 2 1
|
||||
1 3 2 4 5
|
||||
8 6 4 4 1
|
||||
1 3 6 7 9
|
||||
File diff suppressed because it is too large
Load Diff
Executable
BIN
Binary file not shown.
@@ -0,0 +1,87 @@
|
||||
package aoc2024day2
|
||||
|
||||
import "core:fmt"
|
||||
import "core:math"
|
||||
import "core:os"
|
||||
import "core:strconv"
|
||||
import "core:strings"
|
||||
|
||||
EXAMPLE_INPUT_PATH :: "example.txt"
|
||||
PUZZLE_INPUT_PATH :: "input.txt"
|
||||
|
||||
main :: proc() {
|
||||
path := len(os.args) == 2 ? os.args[1] : EXAMPLE_INPUT_PATH
|
||||
data := os.read_entire_file(path) or_else panic(fmt.tprintf("failed to read", path))
|
||||
defer delete(data)
|
||||
|
||||
numbers: [dynamic]int
|
||||
defer delete(numbers)
|
||||
|
||||
counter1 := 0
|
||||
counter2 := 0
|
||||
|
||||
it := string(data)
|
||||
for line in strings.split_lines_iterator(&it) {
|
||||
for word in strings.split(line, " ") {
|
||||
number := strconv.parse_int(word) or_else panic(fmt.tprintf("failed to parse", word))
|
||||
append(&numbers, number)
|
||||
}
|
||||
|
||||
diffs := diff(&numbers)
|
||||
counter1 += int(safe(&diffs))
|
||||
|
||||
// or-reduction on safe of each tolerated diff
|
||||
b := false
|
||||
for &combination in tolerate(&numbers) {
|
||||
diffs := diff(&combination)
|
||||
if safe(&diffs) {
|
||||
b = true
|
||||
break
|
||||
}
|
||||
}
|
||||
counter2 += int(b)
|
||||
|
||||
clear(&numbers)
|
||||
}
|
||||
|
||||
fmt.println("part 1: there were", counter1, "safe reports.")
|
||||
fmt.println("part 2: there were", counter2, "safe reports.")
|
||||
}
|
||||
|
||||
diff :: proc(nums: ^[dynamic]int) -> [dynamic]int {
|
||||
out: [dynamic]int
|
||||
for cur, i in nums {
|
||||
if len(nums) - 1 == i {break}
|
||||
next := nums[i + 1]
|
||||
append(&out, next - cur)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
safe :: proc(diffs: ^[dynamic]int) -> bool {
|
||||
for cur, i in diffs {
|
||||
// not on last element of list ? ... : default
|
||||
next := len(diffs) - 1 != i ? diffs[i + 1] : cur
|
||||
// not (same sign and greater than zero && at most 3)
|
||||
if !(cur * next > 0 && cur * cur <= 9) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
// fmt.println(safe ? "safe" : "unsafe")
|
||||
return true
|
||||
}
|
||||
|
||||
tolerate :: proc(diffs: ^[dynamic]int) -> [dynamic][dynamic]int {
|
||||
out: [dynamic][dynamic]int
|
||||
for d, i in diffs {
|
||||
new: [dynamic]int
|
||||
append(&out, new)
|
||||
}
|
||||
for d, i in diffs {
|
||||
start: []int = diffs^[0:i]
|
||||
end: []int = diffs^[i + 1:len(diffs)]
|
||||
append(&out[i], ..start)
|
||||
append(&out[i], ..end)
|
||||
}
|
||||
return out
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))
|
||||
@@ -0,0 +1 @@
|
||||
xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))
|
||||
@@ -0,0 +1,6 @@
|
||||
*who():mul(420,173)what()*~why() select()how()-mul(448,672)mul(914,202){^{why()];<&;/mul(748,792)what(),$from()what()when()mul(399,982)<;)]]mul(347,549)@;*);mul(655,663) @select()~%,$#mul(535,284)*--@()]+~mul(2,513)why()mul(239,99)!<mul(2,988)@mul(971,404)?&from()mul(660,516)-;what();how()+!why()mul(612,994)'[mul(253,728)<-mul(208,621)>?}( #]mul(162,534)#+how()}<&what();mul(685,182)mul(146,549)mul(659,511)mul(283,734)*/don't()/mul(579,121)what()mul(790,893)where()@)-{#!who()((mul(985,741)when(),$where()>do()<~''-~-mul(961,154),]select()(select()@what()mul(840,357)] when()mul(47,948))]?what()+*;+mul(331,33)who();&~~mul(983,456)mul(660,500)who()mul(414,834)where()^({>mul(961,732)#^]how() mul(869,618)mul(265,208)!when()*]mul(803,747)>*&+what()+,['mul(490,565)> >/*%mul(238,882)%+$;%&,/mul(629,355){{'/?-who():!mul(441,172):[?;mul(628,85)%%{how()]^>why()>mul(509,935)where()/]select()mul(727,783)?^@why()from()>&mul(75,582)<~!%from(){from() mul(616,901)''why()%-from()>>mul(568,812)%(*mul(833,395)$who()& ;how(112,924)why()?mul(734,354)mul(344,367):what()mul(884,545)when(753,136):{select()[mul(981,829)~!<who()>why()mul(444,22)mul(257,636)from()why();&mul(603,941)}-when()&mul(109,476)#)from()when()+;?,mul(149,108)mul(716,634)/~>:&#?mul(919,396)@why() (who()~!mul(949,950)~~:why()&mul(949,808)mul(678,162)&mul(862,475)?++:, mul(750,321)(# why()#{@/select(282,886)mul(953,52),~from()mul(408,319)?@*:#mul(308,330)select(895,376)&>#-when()do()!@*how(890,967)when()mul(607,743),^,when()}$*&mul(737,198))#[!?mul(979,606),-@+'mul(223,381)when(){+<when()%]{*mulwhere()how()<)*?&where()//mul(875,817)when()from()%how())@#]<who()mul(799,646)where()+((how():!+!why()mul(162,552)@?select()>;{mul(623,192)-}@when()@'who()select()how()#don't()!where()@@&}&mul(853,100)]{]~mul(501,746)-? *mul(599,24)mul(141,255)mul(922,727)*select()>how()$who(){+mul(544,731)/from()how()who();@select()mul(609,809)?$(/why()from())mul(498,52)]:when()mul(60,285)@'$)why() %<']do()!from()from()who()::mul(894,43)#@:$mul(731,263)why()select()who(){mul(516,369)how()who()do()$;&$/[;;[mul(655,571)]from()*what()mul(192,59)+]?select()mul(453,68)from()mul?+mul(281,2){why()]~{!,mul(823,635)^/)where()]who() @'$mul(660,562):%where()why()why()%~how()mul(437,42)mul(590,3)~-mul(428,918)>what()why()&?when(742,360)?mul(786,567)%from()when()-mul(367,375)*}why()mul(455,204)/]<,]+mul(819,196)from()@mul><when()+(where()^}&mul(605,973)&where()&^^<%why()[)mul(227,87)where() }mul(762,536)$%~<:>mul(212,199)what()/where(462,172)~when()select()^mul(794,611)mul(484,833)( ?mul(877,152)]what()mul(758,157(][&+how(){>)mul(408,379);}{when()mul(731,259)#?how()mul(246,943)who()@what(830,854){-+>@~:don't()mul(703,111) #^what()<>^do()>,>^+!mul(57,220)#<${#why()when(457,676)>what()mul(199,247)mul(768,629)
|
||||
)'how()<(/)'';mul(867,986))@mul(909,468)?>from()why():<*select(700,257)>don't()mul(294:why()/&^}select()[:{mul(96,677)from()#?-when()%&&'what()mul(806,612)who()@who()<$select()mul(491,724) mul(47,119)#)^who()'mul(526,381)mul(24,969)from()[;mul(189,60)$<>when(565,624)]+#what()<mul(175,572)#{when())+*(~<mul(993,825)where()from(467,409)from()#@+){mul(67,355)& from()!))where();}mul(808,139);<^who(842,199)*!+]{^mulfrom()mul(454,197)select()#how();?~$who()(!mul(854,101)>$[where()why()don't()[]):-who()',select(576,158)what()mul(79,672)--<>[-[mul(248,857)!<^when()]mul(881,761)^!):how()@mul(812,759)what()*>why()+~*-mul(993,256)${-when()mul-&/!what(781,304)why():mul(627,605) >(&%!where(){why(296,454)mul(990,864)!,&(select()'^mul(537,400)what()why()?-where()@:mul(752how(231,812)why()-how()where(956,169)mul(146,184)~}@%],$(who()@mul(716,486)+why()/what()+:{mul(42,180)$when()'][*how()>&mul(611,512)what(155,381):>;(mul(423,432)$,when()&where()mul(976,409)why()@ >why()~#-select()@mul(50,854)$@#mul(42,58)$when()!-#mul(326,406)~where(195,918)where()mul(3,647);['~];$how()why()what()mul(966,495)mul(324,653)mul(47,577)#+(*+^$)mul(144,392)/mul(135,506)what(729,718)don't()%'>mul(609,314)%:>*~mul(120,925)mul(765,209){select()$:#mul(741-$%!;mul(166,556)when(523,779)select())mul(820,823)%~:where())/{when()/mul+where()why()+{;mul(41,341)>~>+mul(960,552) do()who()mul(381,244)?(@+@mul(287,560)!mul(954,480)$where()mul(914,431)}!::what()(}!who()+mul(586,399)from()@why()?when()how()when()when()mul(802,73)mul(14,93)$what()why()%when()(mul(569,2): mul(793,2)mul(301,988){ mul(732,16)why()select()/^{mul(573,997)()*;;from()){mul(477,194) [mul(180,519)from()!where()@$mul(797,512/;select()?who()+how()mul(176,169)from()$<!mul(830,661)(+[mul(466,467)do(),{ ('<mul(145,237)[why()how(111,297)+from()&,mul(369,942)<<select()+;>when()&do()>*,when(277,359){mul(326,605)how()where()}<}:/mul(852,42)what()$)mul(12,636)mul(991,890)]^where()~'do()where()?when()-})@mul(283,368)!,@!$]$@ do()/#'why()-mul(972,409),mul(69how()!*+$where()')where(768,54)&mul(813,972)>select()]+] %#'?mul(701,332who()mul(471,905)+,mul(190,8)how()who()/mul(734,501)select()>how();from(){mul(533,838)who(386,331)how(356,935)[;}mul(373,528)%'*%mul(691,404)@'{^mul(885,376)why()-*mul(439,454)mul(743,477)((!what()][mul(606,298)[/who())how()[>mul(306,944)'when()'what()when()what();}@-mul(294,922)[why()don't()why())~![mul(516where(380,379)#who()mul(564,911)>?where()mul(53,783)#why(725,816)mul(646,866)+select()when()(mul(737,165)/mul(869,809)}mul(207,700)when(),&why()select()&@who()mul(773,864)when()$<(why()mul(320,655)^mul(131,141)when(),mul(634,514)select()&mul(483,605)+mul(934,936)where()]%:(who()]*from()mul(360,239)what(594,220)/%how()select():&#who(725,14)/mul(770,595~%%$]mul(213,299)*#[*mul(116,151)#<&!@>how()'from() mul(605,523)from()(who()mul(593,247)>select(),'who();mul(449,779)*how()+how()how()mul(956,857)do():~mul(826,140)^mul(224,267)<)who()?{-^~:mul(789,774)][*why()@-mul(443,401) what()mul(823,217)when(){*/why();>what(637,904),who()mul(264,561)]%-(how()how()mul(361,672)}when()(<!when()when()<mul(242,102)&;who()how()mul(621,459),where()select()$%$where()mul(882,598)
|
||||
how()#what()where()$who())*<do()when()&[*(select(973,490)~mul(229,108)}%;%don't()mul(597,35)^mul(573,106)!]/{}]what()when()%?do()mul(374,846)?%from(74,478){who()mul(191,307)!}{#[)mul(372,182)(why()(do()mul(113,448)+>when()-mul(850,888)(:-'do()-+-&*mul(798,594)when()-^(<why()from()<mul(704,684)%/why()$don't()$}$when()from()-*-}mul(408,178)why()}+$-&how()mul(572,313)+@]&mul(400,367)how()when()]<who()<'mul(399,406)%]> )(mul(990,700)mul(822,80)mul(803,211)+ %]who()>*mul(614,212)where();how()what()mul(969,702)~[@mul(916,424)*(from()mul(119,685)<mul(889,37)from())$[who()[-(<how()mul(608,492)-[#]:how()mul(189,469),^>'mul(242,632),mul(236,192)&}(-;from()!mul(409,803)mul(26,832)mul(179,583)%;mul(331,141)&select()mul(586,628({)~:mul(201,618)$from()]what()?*mul(346,455)mul(186,191)where() -when() ~&[)why()mul(227,155){&~mul(572,168)(from()}-:when()#where()mul(532,271)when()??:)'mul(482,565)>/^;mul(849,201))&~~-how()$mul(537,900)?+)select()mul(562,60)how()mul(80,960)/&+'!what(),@@mul(741,753),do()!>from())(~mul(434,18)mul(662,562)-'why()mul(205,696)what();from()who()mul(656,755)mul(197,722)?@what()*?*'~mul(935,826)')'%}mul(675,242)/{~mul(119,521)+how()mul(644,874)select():from()mul(538,772)why()~[%#}how()&[mul(911,456)]when()where()$)?mul(422,424)?how()!when()]+mul(931,256%!#<mul(3,464){*}*/mul(618,975)(:,who()]mul(842,565>where()?when(689,268)-^<$mul(303,826)#what()$mul(400,12)~#mul(81,564)>}who())?/+$mul(871,726)?: [how()/}what()mul(694,277)>from()from()/**??)mul(395,609))^when()why()mul(615,463),why())@*when())select()mul(363,846)'&*)!]?)#mul(355,458)- don't()^ ^-'^what()-how()&mul(631,476)/where()^[+*>;mul(89,941)^$&}from(),'do())who()select()'^+& when();mul(434,156)(:@/select()>+from()*how()mul(508,595)mul(779(/&}mul(583,481)mul(624,130)$;??- :]^mul(66,470)mul(169,109)!{,@@]*)mul(984,230>}'%?#&~#don't()why()%,#<:$'mul(251,527):select()}mul(213,941)}^$#@mul(680,847)}$,)who()^~^why(),mul+){where()where()don't()^,#;when()>why()-:mul(226,208)-<from()<where()]what()&^*don't();)&from()^,mul(715,140)!<&how();{mul(300,628)($+ where(497,386);;what()how(612,199)mul(112,519))([mul(995,792)where(),{where():{$where(397,933)!mul(10,240),#who()mul(690when()%what()}~]where()do()^-'!from()!where():where()&mul(785,298)>who()#!~;<([mul(34,783)[when()from()]who()from()mul(421,685)mul(55,857)% -$/'when()]do()%mul(295,33)/mul(211,988)mul(492,249)select()//from()!mul(678,139)?what()why()?/!why()what()mul(62,558);~+ [don't()select()^from()~ +what()where(){-mul(46,220)why()>@~from()?{mul(78,499)/mul(13,468}{'[select()-}};do();]'}^(>-why()who()mul(458@~~who(),@;)why()/mul(56,660)mul(555,777)/$mul(660,540)@why()what()from()(!mul(317,310)^,&-+why()why()*mul(163,392)what(){}+}don't()why()%<select()}/mul(693,615% ]who()what();'>mul(593,212)+what()@mul(235,578)where()~?don't()select()&where()/#[~,+mul(540,363)who()mul(460,343)#where()select(63,367)'&^!mul(553,169)#^$ <why()mul(22,209)]?mul(129,490)]+mul(824,295)who()(!!mul(878,169)how()>mul(521,969)where()*&select()&~why()select()/{don't();mul(853,399)$mul(808,9))how() }when()don't()^>(-mul(938,463)/*#!/usr/bin/perl^)when():mul(751,26)
|
||||
mul(542,820)select()$mul(103,40)]how()? :mul(682,891))mul(837,527)+when() >mul(441,283)^ mul(603,169)select()%!mul(772,674)from()how()@^mul(222,674)from()who(),select(102,983)who()~[mul(697,571)$]:^from()~{?mul(763,249)}:,why()select(188,51)when()$select()how(412,892)[do()why()what(),&mul(258,614)mul(210,257)-)^mul(898,947)#mul(134,666)~,^mul(757,293)(where()!mul(977,413)when()))what(58,623)mul(706,330)who()where()who()select()mul(286,97) ]why())/mul(876,454)>}mul(412,509how() )+who()mul(402,110)/-%}where()when()do();^what())?()$]mul(257,787),from()!+~}*mul(250,775)<why()mul(826,349)!select()what()$mul(668,426)]/ {[mul(552,132)##why():mul(289,363)~',what()don't()%where()~who()what()#)@#mul(815,869)}where(){~}&mul(401,620)-where()]]!#+@mul(787,918)@}:mul(231,854(mul(488,659)?mul(267@when(211,508)where()*],mul(894,288)how(){mul(633,28)? (///&mul(235,462)&'how()mul(6,249)%~&!why()how();+)don't()?@,mul(291,493)mul(731,513)mul(650,232))+;![when()mul(244,943)mul(810,586~ ~mul(133,729))^&%''@~who()don't(){mul(850^'why()mul(91,172)^#&] who()%mul(403,294)-~)where())#<mul(224,258)+,}$$?when(925,148)mul(83,251)/mul(570,58),+how()why()mul(130,998):- ( what()where()[what(),mul(221,150)$$,do()%;%mul(920,992)[mul(314,990)#{select()&mul(265,592)mul(197,785)<(+{/? why(){~mul(144,77,!~select()-(*when()mul(227,184)?how()^? }mul(576,268)'>when()mul(735,684)why()(from(){)^how()from()!mul(749,268) how()mul(613,859)when(424,496)from()~^[mul(450,275)how()mul(41,682)when():when()what()when()*'[how()do()&'where(271,301)@}select()~mul(745,186)',[mul(585,614)what()^@when(224,919)/#>,-mul(374,69)-)< who()~when()why(),mul(30,174)-[what(357,897)where()who()@mul(10,444)'how()'when()what()&$mul(809,809)who()?+(~what();;mul(531,509)^^^%(~~mul(119,968){why();who(677,751)who()!mul(161,854)^^ how()](mul(481,323),/<how()why()&?mul(878,699)~ -mul(658,842)when()/!( ~ mul(593,125)^mul(486,116)+'!(#}:%@mul(922,260)~mul(163,921):what()'<what(120,761)/:select()don't()select()select()}<-when()?}mul(601,494)mul(184,68)mul(703,694)&;;!}![mul(255,743)who()* ^select()%mul(772,315)what()-mul(799,280):who()why();!what()]+what()how(847,982)mul(276,198);select()<*;>:,@mul(293,345)/)what()%!what()<~mul(959,852)/+$why()^<!-mul(756,324)how()>why()where(),@mul(281,314)#when()%]! -mul(347{why()select()why():)^~mul(10,106)%+?%when()mul(941,657)select()when()&,@@'@mul(250,253)#,what()mul(539,823);^*<[mul(422,155)who(){$:-&#mul:mul(61,174):why()'where()don't()select()<&+!/@&<-mul(596,236)~mul(339,838)'}mul(263,931)!how()mul(65,701)from()'/>/)mul(879,804)how() {*((mul(213,689)*[when()}what()?where())mul(727,958)mul(246,840)+mul(150,479)>?~from()*mul(552,678)?don't()$~?'mul(97,380)>mul(968,76)}#!from()mul(435,362why()#}when()*[how()'!#mul(357,345)}?why()[[mul(356,875)%when())$#mul{from()mul(289,657)from(681,624)'<;who()mul(514,298);{ mul-/[(:who():mul(789,109)where()%}what(435,852)mul(330,192)why();)$-]+mul(617,542)mul(244,889)?*%'>!mul(799,990)from()(mul(234,708)
|
||||
@; ;?&]?#mul(577,752)%*)$&why()!%[mul(7,487)how(),@]select()$mul(38-?-+:^[from()#mul(252,810)who()]<+<who()how()]mul(85{$+who()mul(30,63)~who(743,434)~;mul(808,964)~?mul(459,384)>!)mul(976,357)[}mul(341,264)/#select(),%select()&mul(547,552)where()from()@+}#:mul(592,61)&how()what();select()!^select()(mul(273,4)'/^mul(446,170)%]]'~+mul(678,454)when()}select())/?#+}mul(180,876)-%%why()mul(255,652)]why()$#!mul(114,812)-?mul(207,511)<who()<>[$how()+}^mul(790,315)%who()/&<mul(631,708)+%+mul(674,272)when(792,225)&~how()}+how()mul(342 /where()how()who(){<{~mul(848,950)>]do()]#@why()/mul(743,708)mul(430,155)+what()(what()'who()$<;mul(700,543)mul(574,126)mul(139,29)who()what() mul(47,32)what() [;don't(),%who() ~}{mul(176,682)>@~select()when()# %,@mul(808,816):~^)where(629,778)%>+'@mul(177,383)mul(29;what()@*mul(324,53)?'?$~-mul(509,507)$}where(929,765) ~%]what()&mul(325,403)how()-<from()&where()}who(){mul(505,703)select(107,676)&mul(252,930)select()(@$?*;mul(143,564)from()':select()do()]mul(130,866)how()#?select()&@who(811,263)why()mul%[(;&;mul(818,893)mul(654,383)@(/&]?don't()*>when()@how()>mul(900,560)what();@)$select(723,538) +)'mul(899,730)},}$select()*~!from(872,462)mul(269,888)+//)<(how()mul(688,635)#>$+)mul(62,201)from()/@,*<,:{mul(808[!-from(),why()~@'{mul(719,116) don't()+where():)mul(139,220)what()*>who()mul(162,455)who()~mul(460,418)<>&?:/&}from():mul(238,979)&/!@'%~+mul(863,124)'~-*select()[@:do()why(124,979) [{'why():#who()how()mul(38,201)&/when();+mul(678,638):}>:$*select()mul(367,239),){*mul(512?>([what()@ do()[-&mul(39,285)mul(97,17)where(){^do()!:mul(347{who()'mul(316,561);mul(537,106)how(),(!mul(785,385)mul(13,891)~why()~[do()(+]who()<)mul(878,575[mul(295,693)#<where()(++mul(547,320))*-;>:!when()%why()mul(293,288);:what()>^^%(<$mul(640,998)from()}mul(340,293)mul(759,91)&(#mul(831,471)why()why()from()mulwho()who()[[<mul(703,622)how()select()select(712,26)mul(936,215)who();who()<[mul(615,207)*mul(662,445)what(670,709)when()!{mul(21,612)where()/from()~mul(144,583)how()!>^'*mul(210,542)where()%what()~?:,-don't()!mul(305,106)+#@!&,do()~%when()mul(318,660)from()when() why():$-[mul(589,949)@&do()?from()mul(455,593)${!*<~*why()#mul(371,828)where()%({ +%$mul(318,225):where()#-?#%mul(816,5)mul(363,524)mul(580,821)/where()what()*{where();mul(223];mul(830,758)~^ why()/?,>why()mul(787,428)( --'who()what()$~mul(314,163)[what()/*~<(</-mul(602,163)@!when()]mul(997,438)<>?#?[ &select())mul(746,865)mul(101,592))}mul(133,751),;',from()mul(226%how()select()/{$!#select(553,217)do()%}mul(538,699))~when()$?* (what()}mul(755,507)+from()who()who()]how(){--[mul(483,410):' -do()where()$}mul(33,473)mul(835,106)$ {)mul(790,297)how()*where()select()where()*,mul(739,441)mul(561,91)]what()[select()%;what(){mul(601,44where()'):where()(/}<+;mul(956,550)}when()[mul(326,936)<where()~@-mul(238,48)/when()'what()'when()mul(331,847)where()'?don't()>where()how();!from()-mul!/$>?mul(133,674)}what()^*}from()~!mul(39,598)+ mul(119,823)where()$$'when()[mul(524,9)&<<@$-mul(473,929)<why()!:/#-mul(581,168)+-from()*@?mul(217,47)/who()what();select()&don't()+?;mul(840,326)what()<^^when()mul(618,587){select(870,163)how()what()mul(304,775)
|
||||
what()(!what(),^$mul(929,706)**]+mul(518,107)from()@@!when()where()#] mul(353,511)<who()from()don't(){-^mul(269,200)(}mul(691,529)){@<~?where()mul(665,863)$^;{$#mul(571,747)[]mul,mul(641,438)(who()when(832,16)do()~why()who()why()<who()where()#,mul(571,105)!mul(322,339)who()?-:]&%mul(667,821)-] ?who()[,]{who()mul(822,144):select()mul(696,806)how()#,[,]mul(98,576)who(6,143)who()$;^>&mul(154,39)^*why()mul(454,972)>mul(819,718))!select() #{mul(176,840<why(53,917)do()]who()&<from()why()/mul(222,418)select()}mul(53,240)mul(561,784)~mul(304,320)mul(50,387)select()(@%<mul(185,493)when()!/;select()+,why()'mul(423,24)*%[-:what()?'mul(968,778)[?what()}!how()how()%%where()mul(694,257)~~&}how()<),)>mul(989,933)%mul(553,654)/where())+what()what()]%mul(293,835):#/'@-when())$'mul(548,948)?who()-where()when()/when()who()where()<don't()(&from()~why()~%-when(){mul(941,861)'when()who()mul(757,163)where(){'*who() {mul(430,376)(>[}@&when(225,152)do()why()!why()-;how()mul(941,10)when(798,196)[<:<select(592,80)<<mul(216,585)/how():@$<when()mul(730,717)don't()}[{[^who(677,991)]~mul(685,354)$~'*)^<?mul(231,11)@&$&>)%mul(9,571)from()#[*what()&&)$/mul(507,991):#?$$<('mul(959,970)^what()what()'where()%@from()%mul(508,137)}mul(230,238)<when():mul(874,283)${$+?-don't()&!select())who()from();where()/mul(837,931)when()how()(mul(345,324)>]<@!,who()where()#mul(636,897)?why()%]when()?/^)where()don't()select()>@+(!mul(215,107):;where();where()mul(237,981);who()[from()>*<mul(85,235) select()mul(696,477);(where()&/)*what()+ mul(838,830)don't()how()what()*$#>,,;mul(357,549)!{(mul(313,524):mul(172,631)-()mul(197,822)from(510,614);how():(>(mul(450,700)&when()@'when():>&mul(572,27)]select()how()/how()~ mul(427,506)'select()%&how(955,693)~$&[why()mul(670,224)@^'>;why()#where(38,295)mul(265,471)^mul(241,265)*#+{select()when()do()from()<why()mul(576,456)^don't()where()select()<)+?where(),&mul(670,731)mul(641,391)*?(what()#*;:mul(736,498)(from(656,887)from()&from()@do()~when(){why()mul(219,587)*?who()',what()+mul(581,478)${$-mul(316,750){+>^@>mul(444,279)}what()from(),!what()+mul(233,30))%/(&mul(24,452)how()who()where(241,512)>where(),from()^>[mul(337,620)+from(296,671)[~ who()where()}'mul(478,339)<don't()~+<*what()mul(812,697)]why()&why(644,814)when():what()when()mul(652,371)(];#(]?<what()+do()where(64,166)@when()&>@mul(963,388)who()[select()$&mul(268,170)!;select()*)mul(192,33)what()where()mul(497,317){<+do()mul(274,822)how()why()+mul(286,147)mul(377,935)mul(696,807)^when()select()>don't())from())!when()<^mul(799,142)'where()^who()mul(616,986)from()*/mul(697,100)%(select(698,850)don't()%{from(775,182)/@}/?]mul(208,63)~~],mul(15,121)({~mul(704,468)}select()from():?/[what(){mul(707,923),when()mul(253,50),-)how()^#*::select()mul(473,468)what()$#}#:/$how()+mul(569,78)]<>(when()mul(394,997)-mul(184,736)@(@/;%~what()mul(827,383)!#)who())'mul(27,745)-$mul(246,974)how()<,$,$#mul(211,698)select()! when()mul(40,60)]why()mul(98,533)?#)(mul(442,333)who()mul(645,711)how()why(507,343)<#,mul(267,790)select()from()/]]:select()~mul(27,928)/#mul(443,725)~how()@:why()how()%mul(963,554)%mul(490,273)(@ ;-$@$mul(309,347)(mul(830,444)+'}from(){how()#&:why()
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,119 @@
|
||||
package aoc2024day3
|
||||
|
||||
import "core:fmt"
|
||||
import "core:os"
|
||||
import "core:strconv"
|
||||
import "core:strings"
|
||||
import "core:unicode"
|
||||
|
||||
EXAMPLE_INPUT_PATH :: "example.txt"
|
||||
PUZZLE_INPUT_PATH :: "input.txt"
|
||||
|
||||
main :: proc() {
|
||||
fmt.println("result of part 1:", sol(false))
|
||||
fmt.println("result of part 2:", sol(true))
|
||||
}
|
||||
|
||||
sol :: proc(part2 := false) -> int {
|
||||
file_path := len(os.args) == 2 ? os.args[1] : PUZZLE_INPUT_PATH
|
||||
|
||||
input := string(
|
||||
os.read_entire_file_from_filename(file_path) or_else panic(
|
||||
fmt.tprintf("failed to read", file_path),
|
||||
),
|
||||
)
|
||||
|
||||
homebrew_regex := `mul(%,%)`
|
||||
curptr := 0
|
||||
enable_regex := `do()`
|
||||
disable_regex := `don't()`
|
||||
doptr := 0
|
||||
dontptr := 0
|
||||
dontnt := true
|
||||
|
||||
runes: [dynamic]rune
|
||||
defer delete(runes)
|
||||
numbers: [dynamic]int
|
||||
defer delete(numbers)
|
||||
|
||||
for c, i in input {
|
||||
if part2 {
|
||||
// fmt.print(doptr)
|
||||
dontcur := rune(disable_regex[dontptr])
|
||||
if dontptr >= len(disable_regex) - 1 {
|
||||
// fmt.println("false")
|
||||
dontnt = false
|
||||
dontptr = 0
|
||||
doptr = 0
|
||||
}
|
||||
if c == dontcur {
|
||||
dontptr += 1
|
||||
} else {
|
||||
dontptr = 0
|
||||
}
|
||||
docur := rune(enable_regex[doptr])
|
||||
if doptr >= len(enable_regex) - 1 {
|
||||
// fmt.println("true")
|
||||
dontnt = true
|
||||
doptr = 0
|
||||
dontptr = 0
|
||||
}
|
||||
if c == docur {
|
||||
doptr += 1
|
||||
} else {
|
||||
doptr = 0
|
||||
}
|
||||
}
|
||||
|
||||
if curptr >= len(homebrew_regex) {
|
||||
curptr = 0
|
||||
if dontnt {
|
||||
// fmt.println("gg")
|
||||
b: strings.Builder
|
||||
strings.builder_init_none(&b)
|
||||
for r in runes {
|
||||
strings.write_rune(&b, r)
|
||||
}
|
||||
str := strings.to_string(b)
|
||||
for s in strings.split_iterator(&str, ";") {
|
||||
append(
|
||||
&numbers,
|
||||
strconv.parse_int(s) or_else panic(fmt.tprintf("failed to parse", s)),
|
||||
)
|
||||
}
|
||||
}
|
||||
clear(&runes)
|
||||
}
|
||||
cur := rune(homebrew_regex[curptr])
|
||||
if cur == '%' {
|
||||
if unicode.is_digit(c) {
|
||||
append(&runes, c)
|
||||
} else if rune(homebrew_regex[curptr + 1]) == c {
|
||||
curptr += 2
|
||||
append(&runes, ';')
|
||||
} else {
|
||||
// fmt.println("gulag2", curptr)
|
||||
curptr = 0
|
||||
clear(&runes)
|
||||
}
|
||||
} else if cur == c {
|
||||
curptr += 1
|
||||
} else {
|
||||
// fmt.println("gulag", curptr)
|
||||
curptr = 0
|
||||
clear(&runes)
|
||||
}
|
||||
}
|
||||
|
||||
// fmt.println(numbers)
|
||||
|
||||
result := 0
|
||||
for n, i in numbers {
|
||||
if i % 2 == 1 {continue}
|
||||
if len(numbers) - 1 == i {break}
|
||||
next := numbers[i + 1]
|
||||
result += next * n
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
2333133121414131402
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,173 @@
|
||||
package aoc2024day9
|
||||
|
||||
import "core:container/queue"
|
||||
import "core:fmt"
|
||||
import "core:os"
|
||||
import "core:slice"
|
||||
import "core:strconv"
|
||||
import "core:unicode"
|
||||
|
||||
PUZZLE_INPUT_PATH :: "input.txt"
|
||||
EXAMPLE_INPUT_PATH :: "example.txt"
|
||||
|
||||
main :: proc() {
|
||||
path := len(os.args) == 2 ? os.args[1] : PUZZLE_INPUT_PATH
|
||||
input := string(os.read_entire_file_from_filename(path) or_else panic("damn"))
|
||||
|
||||
fmt.println("part 1:", part1(input))
|
||||
fmt.println("part 2:", part2(input))
|
||||
}
|
||||
|
||||
part2 :: proc(input: string) -> int {
|
||||
mem: [dynamic]int
|
||||
defer delete(mem)
|
||||
free: map[int]int // start_index -> free_space_interval_delta
|
||||
defer delete(free)
|
||||
filesizes: map[int]int // fileid -> block_count
|
||||
defer delete(filesizes)
|
||||
|
||||
next_fileid := 0
|
||||
memptr := 0
|
||||
|
||||
for r, i in input {
|
||||
if !unicode.is_digit(r) {continue}
|
||||
d := strconv._digit_value(r)
|
||||
if i % 2 == 0 { // files
|
||||
for j := 0; j < d; j += 1 {
|
||||
append(&mem, next_fileid)
|
||||
memptr += 1
|
||||
filesizes[next_fileid] = j + 1
|
||||
}
|
||||
next_fileid += 1
|
||||
} else { // free
|
||||
for j := 0; j < d; j += 1 {
|
||||
append(&mem, -1)
|
||||
free[memptr - j] = j + 1
|
||||
memptr += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fmt.println(free)
|
||||
// fmt.println(filesizes)
|
||||
|
||||
used: [dynamic]int
|
||||
defer delete(used)
|
||||
|
||||
#reverse for fid, i in mem {
|
||||
if fid < 0 || slice.contains(used[:], fid) {continue}
|
||||
append(&used, fid)
|
||||
move := false
|
||||
size := filesizes[fid]
|
||||
for f, j in mem {
|
||||
if f >= 0 || !(j in free) {continue} // TODO: scary slow
|
||||
t := free[j]
|
||||
if t >= size {
|
||||
move = true
|
||||
for k in 0 ..< size {
|
||||
mem[j + k] = fid
|
||||
}
|
||||
free[j + size] = t - size
|
||||
break
|
||||
}
|
||||
}
|
||||
if move {
|
||||
for k in 0 ..< size {
|
||||
mem[i - k] = -2
|
||||
}
|
||||
}
|
||||
for m in mem {
|
||||
if m < 0 {
|
||||
fmt.print("x")
|
||||
} else {
|
||||
fmt.print(m)
|
||||
}
|
||||
}
|
||||
fmt.println()
|
||||
}
|
||||
|
||||
// for fid := next_fileid - 1; fid > 0; fid -= 1 {
|
||||
// size := filesizes[fid]
|
||||
// memptr -= size
|
||||
// }
|
||||
|
||||
// keys := slice.map_keys(free) or_else panic("damn2")
|
||||
// slice.sort(keys)
|
||||
// ptr := 0
|
||||
// #reverse for fileid, i in mem {
|
||||
// if fileid < 0 {continue}
|
||||
// cur := mem[memptr - 1]
|
||||
// target := filesizes[cur]
|
||||
// for start, j in keys[ptr:] {
|
||||
// delta := free[start]
|
||||
// if delta < target {continue}
|
||||
// end := delta + start
|
||||
// }
|
||||
// }
|
||||
|
||||
// #reverse for fileid, i in mem {
|
||||
// f := queue.peek_front(&free)^
|
||||
// if queue.len(free) <= 0 || f >= len(mem) {break}
|
||||
// if fileid >= 0 {
|
||||
// mem[f] = fileid
|
||||
// queue.pop_front(&free)
|
||||
// }
|
||||
// pop(&mem)
|
||||
// }
|
||||
|
||||
sum := 0
|
||||
for fileid, i in mem {
|
||||
if fileid < 0 {continue}
|
||||
sum += fileid * i
|
||||
}
|
||||
|
||||
return sum
|
||||
}
|
||||
|
||||
part1 :: proc(input: string) -> int {
|
||||
mem: [dynamic]int
|
||||
defer delete(mem)
|
||||
free: queue.Queue(int)
|
||||
queue.init(&free)
|
||||
defer queue.destroy(&free)
|
||||
|
||||
next_fileid := 0
|
||||
memptr := 0
|
||||
|
||||
for r, i in input {
|
||||
if !unicode.is_digit(r) {continue}
|
||||
d := strconv._digit_value(r)
|
||||
if i % 2 == 0 { // files
|
||||
for j := 0; j < d; j += 1 {
|
||||
append(&mem, next_fileid)
|
||||
memptr += 1
|
||||
}
|
||||
next_fileid += 1
|
||||
} else { // free
|
||||
for j := 0; j < d; j += 1 {
|
||||
append(&mem, -1)
|
||||
queue.push_back(&free, memptr)
|
||||
memptr += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#reverse for fileid, i in mem {
|
||||
f := queue.peek_front(&free)^
|
||||
if queue.len(free) <= 0 || f >= len(mem) {break}
|
||||
if fileid >= 0 {
|
||||
mem[f] = fileid
|
||||
queue.pop_front(&free)
|
||||
}
|
||||
pop(&mem)
|
||||
}
|
||||
|
||||
sum := 0
|
||||
for fileid, i in mem {
|
||||
if fileid < 0 {continue}
|
||||
sum += fileid * i
|
||||
// fmt.println(fileid, i)
|
||||
}
|
||||
|
||||
return sum
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
input([0,1,1,0], [[3], [1,3], [2], [2,3], [0,2], [0,1]], [3,5,4,7]).
|
||||
input([0,0,0,1,0], [[0,2,3,4], [2,3], [0,4], [0,1,2], [1,2,3,4]], [7,5,12,7,2]).
|
||||
input([0,1,1,1,0,1], [[0,1,2,3,4], [0,3,4], [0,1,2,4,5], [1,2]], [10,11,11,5,10,5]).
|
||||
@@ -0,0 +1,46 @@
|
||||
% [.##.] (3) (1,3) (2) (2,3) (0,2) (0,1) {3,5,4,7}
|
||||
% [...#.] (0,2,3,4) (2,3) (0,4) (0,1,2) (1,2,3,4) {7,5,12,7,2}
|
||||
% [.###.#] (0,1,2,3,4) (0,3,4) (0,1,2,4,5) (1,2) {10,11,11,5,10,5}
|
||||
% -> 2 + 3 + 2 = 7
|
||||
|
||||
:- consult('example.pl').
|
||||
|
||||
% Keep your toggle functions
|
||||
toggle(Ls, [], Ls).
|
||||
toggle(Ls, [I|Is], Out) :-
|
||||
nth0(I, Ls, V), flip(V, F), set_nth0(I, Ls, F, T), toggle(T, Is, Out).
|
||||
flip(0, 1). flip(1, 0).
|
||||
set_nth0(0, [_|Rs], V, [V|Rs]).
|
||||
set_nth0(N, [R|Rs], V, [R|Ts]) :- N > 0, N1 is N-1, set_nth0(N1, Rs, V, Ts).
|
||||
|
||||
% Simple iterative deepening - no visited states needed
|
||||
solve(L, _, [], 0) :- maplist(=(1), L).
|
||||
solve(L, Wires, [W|Rest], D) :-
|
||||
D > 0, member(W, Wires),
|
||||
toggle(L, W, L1),
|
||||
D1 is D - 1,
|
||||
solve(L1, Wires, Rest, D1).
|
||||
|
||||
% Find minimal solution
|
||||
min_solve(L, Wires, Steps) :-
|
||||
between(0, 6, Depth), % Limit depth to 6
|
||||
length(Steps, Depth),
|
||||
solve(L, Wires, Steps, Depth).
|
||||
|
||||
|
||||
solve_all :-
|
||||
findall([L,W], input(L,W,_), Inputs),
|
||||
maplist(solve_one, Inputs, Lengths),
|
||||
sum_list(Lengths, Total),
|
||||
format('Total: ~w~n', [Total]).
|
||||
|
||||
solve_one([L,W], MinLen) :-
|
||||
find_min_depth(L, W, MinDepth),
|
||||
MinLen = MinDepth.
|
||||
|
||||
find_min_depth(L, Wires, MinDepth) :-
|
||||
between(0, 6, Depth),
|
||||
length(Steps, Depth),
|
||||
solve(L, Wires, Steps, Depth), !,
|
||||
MinDepth = Depth.
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# day 11
|
||||
|
||||
Parse ← (
|
||||
⊜(∩□⊙(⊜∘⊸≠@ )°$"_: _")⊸≠@\n
|
||||
∧(insert°□°⊟)⊙[]⍉⊟
|
||||
)
|
||||
Go‼ ← ⊙◌path(0°□⍣get|≍^1)^0
|
||||
Part₁ ← ⧻Go‼"you" "out"
|
||||
# Part₂ ← ⧻⊚≡◇(↧∩/↥⌕□"fft"⤙⌕□"dac"≡□)Go‼"svr" "out"
|
||||
Win‼ ← (
|
||||
⊃Go‼^0 "out" Go‼"svr" ^0
|
||||
+⊃(×⊙/+⧻|×⊙⧻/+)∩≡◇(/↥≡/↥⌕^1)
|
||||
)
|
||||
Part₂ ← ↥⊃Win‼"fft" "dac" Win‼"dac" "fft"
|
||||
⍤⤙≍ 5 Part₁ Parse $ aaa: you hhh
|
||||
$ you: bbb ccc
|
||||
$ bbb: ddd eee
|
||||
$ ccc: ddd eee fff
|
||||
$ ddd: ggg
|
||||
$ eee: out
|
||||
$ fff: out
|
||||
$ ggg: out
|
||||
$ hhh: ccc fff iii
|
||||
$ iii: out
|
||||
|
||||
⍤⤙≍ 2 Part₂ Parse $ svr: aaa bbb
|
||||
$ aaa: fft
|
||||
$ fft: ccc
|
||||
$ bbb: tty
|
||||
$ tty: ccc
|
||||
$ ccc: ddd eee
|
||||
$ ddd: hub
|
||||
$ hub: fff
|
||||
$ eee: dac
|
||||
$ dac: fff
|
||||
$ fff: ggg hhh
|
||||
$ ggg: out
|
||||
$ hhh: out
|
||||
|
||||
⍜now(Part₂ Parse &fras "input")
|
||||
@@ -0,0 +1,36 @@
|
||||
# day 11
|
||||
|
||||
Parse ← (
|
||||
⊜(∩□⊙(⊜∘⊸≠@ )°$"_: _")⊸≠@\n
|
||||
∧(insert°□°⊟)⊙[]⍉⊟
|
||||
)
|
||||
Go‼ ← ⊙◌path(0°□memoget|≍^1)^0
|
||||
Part₁ ← ⧻Go‼"you" "out"
|
||||
Part₂ ← ⧻⊚≡◇(↧∩/↥⌕□"fft"⤙⌕□"dac"≡□)Go‼"svr" "out"
|
||||
|
||||
⍤⤙≍ 5 Part₁ Parse $ aaa: you hhh
|
||||
$ you: bbb ccc
|
||||
$ bbb: ddd eee
|
||||
$ ccc: ddd eee fff
|
||||
$ ddd: ggg
|
||||
$ eee: out
|
||||
$ fff: out
|
||||
$ ggg: out
|
||||
$ hhh: ccc fff iii
|
||||
$ iii: out
|
||||
|
||||
⍤⤙≍ 2 Part₂ Parse $ svr: aaa bbb
|
||||
$ aaa: fft
|
||||
$ fft: ccc
|
||||
$ bbb: tty
|
||||
$ tty: ccc
|
||||
$ ccc: ddd eee
|
||||
$ ddd: hub
|
||||
$ hub: fff
|
||||
$ eee: dac
|
||||
$ dac: fff
|
||||
$ fff: ggg hhh
|
||||
$ ggg: out
|
||||
$ hhh: out
|
||||
|
||||
⍜now(Part₂ Parse &fras "input")
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env nu
|
||||
def part-1 [parsed] {
|
||||
$parsed
|
||||
| par-each {
|
||||
|row| where {|x| into string
|
||||
| split chars
|
||||
| take (($in | length) // 2)
|
||||
| ($in | str join) + ($in | str join)
|
||||
| try {into int} catch {0}
|
||||
| $in == $x
|
||||
}
|
||||
} | flatten | math sum
|
||||
}
|
||||
|
||||
let input = open input
|
||||
let parsed = $input
|
||||
| str trim
|
||||
| lines
|
||||
| str join
|
||||
| split row ','
|
||||
| split column '-'
|
||||
| rename l u
|
||||
| into int l u
|
||||
| each {|row| $row.l..$row.u}
|
||||
|
||||
timeit {print (part-1 $parsed)}
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,76 @@
|
||||
package day2
|
||||
|
||||
import "core:fmt"
|
||||
import "core:math"
|
||||
import "core:strconv"
|
||||
import "core:strings"
|
||||
|
||||
EXAMPLE_INPUT :: "11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124"
|
||||
RANGE_COUNT :: 11
|
||||
|
||||
Data :: [RANGE_COUNT][2]int
|
||||
|
||||
// split input string into an array of each range end point
|
||||
parse :: proc(input: string, allocator := context.allocator) -> (data: ^Data, ok: bool) {
|
||||
defer free_all(context.temp_allocator)
|
||||
data = new(Data, allocator)
|
||||
ranges, err := strings.split_n(input, ",", RANGE_COUNT, context.temp_allocator)
|
||||
if err != .None do return nil, false
|
||||
for range, i in ranges {
|
||||
if i > RANGE_COUNT do break
|
||||
endpoints, err := strings.split_n(range, "-", 2, context.temp_allocator)
|
||||
if err != .None do return nil, false
|
||||
for j := 0; j < 2; j += 1 do data[i][j] = strconv.parse_int(endpoints[j]) or_return
|
||||
}
|
||||
return data, true
|
||||
}
|
||||
|
||||
part_1 :: proc(data: ^Data) -> (sum: int) {
|
||||
defer free_all(context.temp_allocator)
|
||||
sum = 0
|
||||
for range in data {
|
||||
start := range[0]
|
||||
end := range[1]
|
||||
start_digit_count := int(math.log10(f32(start))) + 1
|
||||
end_digit_count := int(math.log10(f32(end))) + 1
|
||||
if start_digit_count == end_digit_count && start_digit_count % 2 != 0 do continue
|
||||
if start_digit_count % 2 != 0 {
|
||||
start = end
|
||||
start_digit_count = end_digit_count
|
||||
}
|
||||
if end_digit_count % 2 != 0 {
|
||||
end = start
|
||||
end_digit_count = start_digit_count
|
||||
}
|
||||
for j := strconv.atoi(string(start)[:start_digit_count / 2 + 1]);
|
||||
j < strconv.atoi(string(end)[:end_digit_count / 2 + 1]);
|
||||
j += 1 {}
|
||||
start_str := make([]u8, start_digit_count, context.temp_allocator)
|
||||
strconv.itoa(start_str, start)
|
||||
for i := 0; i < start_digit_count; i += 1 {
|
||||
if i >= start_digit_count / 2 {
|
||||
start_str[i] = start_str[i % (start_digit_count / 2)]
|
||||
}
|
||||
}
|
||||
end_str := make([]u8, end_digit_count, context.temp_allocator)
|
||||
strconv.itoa(end_str, end)
|
||||
for i := 0; i < end_digit_count; i += 1 {
|
||||
if i >= end_digit_count / 2 {
|
||||
end_str[i] = end_str[i % (end_digit_count / 2)]
|
||||
}
|
||||
}
|
||||
fmt.println(start, end, strconv.atoi(string(start_str)), strconv.atoi(string(end_str)))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
data, ok := parse(EXAMPLE_INPUT)
|
||||
if !ok do panic("failed to parse")
|
||||
defer free(data)
|
||||
|
||||
part_1(data)
|
||||
|
||||
fmt.println(data)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package day3
|
||||
|
||||
import "core:fmt"
|
||||
import "core:mem"
|
||||
import "core:os"
|
||||
import "core:strings"
|
||||
import "core:time"
|
||||
|
||||
PUZZLE_INPUT :: `
|
||||
987654321111111
|
||||
811111111111119
|
||||
234234234234278
|
||||
818181911112111
|
||||
`
|
||||
|
||||
Data_Is_Empty_Error :: distinct struct{}
|
||||
|
||||
Data_Is_Ragged_Error :: distinct struct {
|
||||
line: int,
|
||||
}
|
||||
|
||||
Illegal_Token_Error :: distinct struct {
|
||||
line, col: int,
|
||||
token: rune,
|
||||
}
|
||||
|
||||
Parsing_Error :: union {
|
||||
mem.Allocator_Error,
|
||||
Illegal_Token_Error,
|
||||
Data_Is_Ragged_Error,
|
||||
Data_Is_Empty_Error,
|
||||
}
|
||||
|
||||
Grid :: struct {
|
||||
data: []int,
|
||||
rows, cols: int,
|
||||
}
|
||||
|
||||
parse :: proc(input: string, allocator := context.allocator) -> (grid: Grid, err: Parsing_Error) {
|
||||
context.allocator = context.temp_allocator
|
||||
defer context.allocator = allocator
|
||||
|
||||
lines := strings.split_lines(strings.trim_space(input)) or_return
|
||||
if lines[0] == "" do return {}, Data_Is_Empty_Error{}
|
||||
|
||||
rows := len(lines)
|
||||
cols := len(strings.trim_space(lines[0]))
|
||||
|
||||
data := make([dynamic]int, 0, rows * cols, allocator) or_return
|
||||
|
||||
for line, row in lines {
|
||||
clean_line := strings.trim_space(line)
|
||||
if len(clean_line) != cols do return {}, Data_Is_Ragged_Error{row}
|
||||
|
||||
for char, col in clean_line {
|
||||
digit := int(char - '0')
|
||||
if digit < 0 || digit > 9 do return {}, Illegal_Token_Error{row, col, char}
|
||||
append(&data, digit) or_return
|
||||
}
|
||||
}
|
||||
|
||||
return Grid{data[:], rows, cols}, nil
|
||||
}
|
||||
|
||||
remove_digits :: proc(
|
||||
row: []int,
|
||||
k: int,
|
||||
allocator := context.allocator,
|
||||
) -> (
|
||||
output: []int,
|
||||
err: mem.Allocator_Error,
|
||||
) {
|
||||
stack := make([dynamic]int, 0, len(row) - k, allocator) or_return
|
||||
dels := k
|
||||
for digit in row {
|
||||
for len(stack) > 0 && digit > stack[len(stack) - 1] && dels > 0 {
|
||||
pop(&stack)
|
||||
dels -= 1
|
||||
}
|
||||
append(&stack, digit) or_return
|
||||
}
|
||||
return stack[:], .None
|
||||
}
|
||||
|
||||
process :: proc(row: []int, n: int) -> (output: int, err: mem.Allocator_Error) {
|
||||
digits := remove_digits(row, len(row) - n) or_return
|
||||
for digit in digits[:n] {
|
||||
output = 10 * output + digit
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
solve :: proc(grid: Grid, n: int) -> (solution: int, err: mem.Allocator_Error) {
|
||||
context.allocator = context.temp_allocator
|
||||
|
||||
bank_solutions := make([]int, grid.rows) or_return
|
||||
|
||||
for row in 0 ..< grid.rows {
|
||||
row_data := grid.data[row * grid.cols:(row + 1) * grid.cols]
|
||||
bank_solutions[row] = process(row_data, n) or_return
|
||||
}
|
||||
|
||||
for bank in bank_solutions do solution += bank
|
||||
return
|
||||
}
|
||||
|
||||
part_1 :: proc(grid: Grid) -> (solution: int, err: mem.Allocator_Error) {
|
||||
return solve(grid, 2)
|
||||
}
|
||||
|
||||
part_2 :: proc(grid: Grid) -> (solution: int, err: mem.Allocator_Error) {
|
||||
return solve(grid, 12)
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
time_start := time.now()
|
||||
input := string(os.read_entire_file("input") or_else panic("failed to read input"))
|
||||
time_read := time.since(time_start)
|
||||
|
||||
data, parsing_error := parse(input, context.temp_allocator)
|
||||
defer free_all(context.temp_allocator)
|
||||
if parsing_error != nil do fmt.panicf("failed to parse: %v\n", parsing_error)
|
||||
|
||||
time_parse := time.since(time_start) - time_read
|
||||
fmt.println("part 1: ", part_1(data) or_else panic("part 1 failed"))
|
||||
time_solve_1 := time.since(time_start) - time_read - time_parse
|
||||
fmt.println("part 2: ", part_2(data) or_else panic("part 2 failed"))
|
||||
time_solve_2 := time.since(time_start) - time_read - time_parse - time_solve_1
|
||||
time_total := time.since(time_start)
|
||||
|
||||
fmt.println("performance benchmarks [ms]:")
|
||||
fmt.println("total\tread\tparse\tpart 1\tpart 2")
|
||||
fmt.printf(
|
||||
"%.3f\t%.3f\t%.3f\t%.3f\t%.3f\n",
|
||||
time.duration_milliseconds(time_total),
|
||||
time.duration_milliseconds(time_read),
|
||||
time.duration_milliseconds(time_parse),
|
||||
time.duration_milliseconds(time_solve_1),
|
||||
time.duration_milliseconds(time_solve_2),
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
Parse ← (
|
||||
∩(⊜□⊸≠@\n)°$"_\n\n_"
|
||||
⊃(⍉⊟≡◇(∩⋕°$"_-_")|⋅≡◇⋕)
|
||||
)
|
||||
Part₁ ← ⧻⊚/↥⊞(↧≤⤙⊙≤°⊟)
|
||||
Part₂ ← ⧻◴/◇⊂⍚/⍜-(⇡+1)
|
||||
|
||||
⍤⤙≍ 3_14 ⊃[Part₁|Part₂] Parse $ 3-5
|
||||
$ 10-14
|
||||
$ 16-20
|
||||
$ 12-18
|
||||
$
|
||||
$ 1
|
||||
$ 5
|
||||
$ 8
|
||||
$ 11
|
||||
$ 17
|
||||
$ 32
|
||||
|
||||
Part₂ Parse &fras "input.txt"
|
||||
@@ -0,0 +1,16 @@
|
||||
.......S.......
|
||||
...............
|
||||
.......^.......
|
||||
...............
|
||||
......^.^......
|
||||
...............
|
||||
.....^.^.^.....
|
||||
...............
|
||||
....^.^...^....
|
||||
...............
|
||||
...^.^...^.^...
|
||||
...............
|
||||
..^...^.....^..
|
||||
...............
|
||||
.^.^.^.^.^...^.
|
||||
...............
|
||||
@@ -0,0 +1,101 @@
|
||||
package day7
|
||||
|
||||
import "core:fmt"
|
||||
import "core:slice"
|
||||
import "core:strings"
|
||||
import "core:time"
|
||||
|
||||
PUZZLE_INPUT: string : #load("input")
|
||||
|
||||
Pos :: distinct struct {
|
||||
row: int,
|
||||
col: int,
|
||||
}
|
||||
|
||||
Parsed_Data :: struct {
|
||||
lines: []string,
|
||||
rows, cols: int,
|
||||
start: Pos,
|
||||
}
|
||||
|
||||
not_empty_line :: proc(line: string) -> (output: bool) {
|
||||
output = true
|
||||
for char in line do output &&= char == '.'
|
||||
return !output
|
||||
}
|
||||
|
||||
parse :: proc(input: string) -> (output: Parsed_Data) {
|
||||
lines := strings.split_lines(input)
|
||||
output.start = {0, strings.index(lines[0], "S")}
|
||||
output.lines = slice.filter(lines, not_empty_line)
|
||||
output.rows = len(output.lines)
|
||||
output.cols = len(output.lines[0])
|
||||
return
|
||||
}
|
||||
|
||||
solve_part_1 :: proc(data: Parsed_Data) -> (output: int) {
|
||||
beams := make(map[Pos]bool, context.temp_allocator)
|
||||
hit := make(map[Pos]bool, context.temp_allocator)
|
||||
defer free_all(context.temp_allocator)
|
||||
beams[data.start] = true
|
||||
for line, row in data.lines {
|
||||
for char, col in line {
|
||||
for pos, exists in beams {
|
||||
if exists && char == '^' && pos == {row - 1, col} {
|
||||
beams[{row, col + 1}] = true
|
||||
beams[{row, col - 1}] = true
|
||||
hit[{row, col}] = true
|
||||
} else if pos == {row - 1, col} {
|
||||
beams[{row, col}] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return len(hit)
|
||||
}
|
||||
|
||||
solve_part_2 :: proc(data: Parsed_Data) -> (output: int) {
|
||||
memo := make(map[Pos]int)
|
||||
defer delete(memo)
|
||||
|
||||
count_timelines :: proc(lines: []string, row, col: int, memo: ^map[Pos]int) -> int {
|
||||
pos := Pos{row, col}
|
||||
|
||||
// Check memo first
|
||||
if cached, exists := memo[pos]; exists {
|
||||
return cached
|
||||
}
|
||||
|
||||
// Bounds check
|
||||
if row >= len(lines) || col < 0 || col >= len(lines[0]) {
|
||||
memo[pos] = 1
|
||||
return 1
|
||||
}
|
||||
|
||||
char := lines[row][col]
|
||||
result: int
|
||||
|
||||
if char == '^' {
|
||||
left := count_timelines(lines, row + 1, col - 1, memo)
|
||||
right := count_timelines(lines, row + 1, col + 1, memo)
|
||||
result = left + right
|
||||
} else {
|
||||
result = count_timelines(lines, row + 1, col, memo)
|
||||
}
|
||||
|
||||
memo[pos] = result
|
||||
return result
|
||||
}
|
||||
|
||||
return count_timelines(data.lines, data.start.row, data.start.col, &memo)
|
||||
}
|
||||
|
||||
|
||||
main :: proc() {
|
||||
start := time.now()
|
||||
data := parse(PUZZLE_INPUT)
|
||||
fmt.println("part 1 solution:", solve_part_1(data))
|
||||
fmt.println("part 2 solution:", solve_part_2(data))
|
||||
total := time.since(start)
|
||||
fmt.println("total time taken:", total)
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,20 @@
|
||||
162,817,812
|
||||
57,618,57
|
||||
906,360,560
|
||||
592,479,940
|
||||
352,342,300
|
||||
466,668,158
|
||||
542,29,236
|
||||
431,825,988
|
||||
739,650,466
|
||||
52,470,668
|
||||
216,146,977
|
||||
819,987,18
|
||||
117,168,530
|
||||
805,96,715
|
||||
346,949,466
|
||||
970,615,88
|
||||
941,993,340
|
||||
862,61,35
|
||||
984,92,344
|
||||
425,690,689
|
||||
@@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
import "core:fmt"
|
||||
import "core:slice"
|
||||
import "core:strconv"
|
||||
import "core:strings"
|
||||
|
||||
PUZZLE_INPUT: string : #load("example")
|
||||
|
||||
Pos :: distinct struct {
|
||||
x, y, z: int,
|
||||
}
|
||||
|
||||
parse :: proc(input: string) -> (output: []Pos) {
|
||||
lines := strings.split_lines(input)
|
||||
output = make([]Pos, len(lines))
|
||||
digits := make([dynamic]int, context.temp_allocator)
|
||||
defer free_all(context.temp_allocator)
|
||||
nums: [3]int
|
||||
for line, row in lines {
|
||||
for num, i in strings.split(line, ",") do nums[i], _ = strconv.parse_int(num)
|
||||
output[row] = Pos{nums[0], nums[1], nums[2]}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
solve :: proc(data: []Pos) -> (output: int) {
|
||||
context.allocator = context.temp_allocator
|
||||
|
||||
distances := make([]int, len(data) * len(data))
|
||||
for p1, row in data {
|
||||
for p2, col in data {
|
||||
d := Pos{p1.x - p2.x, p1.y - p2.y, p1.z - p2.z}
|
||||
distance := d.x * d.x + d.y * d.y + d.z * d.z
|
||||
distances[row * len(data) + col] = distance == 0 ? 1e9 : distance // TODO: triangle
|
||||
}
|
||||
}
|
||||
fmt.println(distances)
|
||||
shortest := make([]int, len(data))
|
||||
for i in 0 ..< len(data) {
|
||||
row := distances[i * len(data):(i + 1) * len(data)]
|
||||
shortest[i] = slice.min_index(row)
|
||||
}
|
||||
fmt.println(shortest)
|
||||
return
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
fmt.println(solve(parse(PUZZLE_INPUT)))
|
||||
}
|
||||
Reference in New Issue
Block a user