Skip to content

Commit e0db331

Browse files
committed
part 2 very ez gg go next
1 parent fb1dca4 commit e0db331

File tree

3 files changed

+234
-48
lines changed

3 files changed

+234
-48
lines changed

2025/day10/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cache*

2025/day10/p2.sh

Lines changed: 221 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,75 +2,250 @@
22

33
. ../../misc/vardump
44

5+
mkdir -p cache
6+
57
FILE="$1"
68

7-
do_the_math() {
8-
while IFS=, read -a arr; do
9-
max=0
10-
total=0
11-
for ((i=0; i<${#arr[@]}; i++)); do
12-
el=${arr[i]}
13-
if [[ el -gt max ]]; then
14-
max=$el
15-
fi
16-
((total+=el))
17-
done
18-
echo "$((total-max)) ($max-$total)"
19-
done
20-
}
9+
D2B=({0..1}{0..1}{0..1}{0..1})
2110

2211
shwoop() {
2312
while read -a stuff; do
24-
local tmp=${stuff[0]}
13+
local tmp=${stuff[1]}
2514
local len="${#stuff[@]}"
26-
stuff[0]="${stuff[len-1]}"
15+
stuff[1]="${stuff[len-1]}"
2716
stuff[len-1]="${tmp}"
2817
echo "${stuff[@]}"
2918
done
3019
}
3120

32-
make_buckets() {
21+
gauss() {
22+
solved=0
23+
total=0
3324
while read -a row; do
34-
requirements="${row[0]}"
35-
buttons=("${row[@]:1}")
25+
idx="${row[0]}"
26+
cache_key="cache/${FILE}-$idx"
27+
((idx--))
28+
if [[ -f "$cache_key" ]]; then
29+
ans=$(cat "$cache_key")
30+
echo "solved $idx from cache: $ans"
31+
((total+=ans))
32+
continue
33+
fi
34+
# buncha parsing bulllllllogna
35+
requirements="${row[1]}"
36+
buttons=("${row[@]:2}")
37+
echo "requirements:"
38+
vardump requirements
39+
echo "buttons"
40+
vardump buttons
3641
IFS=, read -a reqs <<< $requirements
37-
unset buckets
38-
local -a buckets
39-
for ((i=0; i<${#reqs[@]}; i++)); do
40-
for ((j=0; j<${#buttons[@]}; j++)); do
41-
IFS=, read -a wires <<< "${buttons[j]}"
42+
unset rows
43+
local -a rows
44+
for ((i=0; i<${#reqs[@]}; ++i)); do
45+
r=()
46+
for ((j=0; j<${#buttons[@]}; ++j)); do
47+
IFS=, read -a button <<< "${buttons[j]}"
4248
contains=0
43-
for ((k=0; k<${#wires[@]}; k++)); do
44-
if [[ ${wires[k]} -eq i ]]; then
49+
for ((k=0; k<${#button[@]}; ++k)); do
50+
if [[ "${button[k]}" == $i ]]; then
4551
contains=1
52+
break
4653
fi
4754
done
48-
[[ contains -eq 0 ]] && continue
49-
if [[ -z "${buckets[i]}" ]]; then
50-
buckets[i]=${buttons[j]}
51-
else
52-
buckets[i]="${buckets[i]} ${buttons[j]}"
53-
fi
55+
r+=($contains)
5456
done
57+
rows[i]="${r[@]} ${reqs[i]}"
5558
done
56-
min=10000
57-
key=0
58-
for ((i=0;i<${#buckets[@]};++i)); do
59-
arr=(${buckets[i]})
60-
length=${#arr[@]}
61-
if [[ length -lt min ]]; then
62-
key=$i
63-
min=$length
59+
60+
local h=0
61+
local k=0
62+
local m=${#rows[@]}
63+
local n=${#r[@]}
64+
((n++))
65+
# wikipedia row echelon form algorithm
66+
while ((h<m && k<n)); do
67+
local i_max=0
68+
local max=0
69+
for ((i=h;i<m;++i)); do
70+
r=(${rows[i]})
71+
local v=${r[k]}
72+
v=${v//-/}
73+
if [[ v -gt max ]]; then
74+
max=$v
75+
i_max=$i
76+
fi
77+
done
78+
if [[ max -eq 0 ]]; then
79+
((k++))
80+
else
81+
# swap rows(h, i_max)
82+
local tmp="${rows[h]}"
83+
rows[h]="${rows[i_max]}"
84+
rows[i_max]="$tmp"
85+
for ((i=0;i<m;++i)); do
86+
[[ i -eq h ]] && continue
87+
local row_i=(${rows[i]})
88+
local row_h=(${rows[h]})
89+
num=$((row_i[k]))
90+
denom=$((row_h[k]))
91+
for ((j=k+1;j<n;++j)); do
92+
local tnum=${num//-/}
93+
((tnum*=row_h[j]))
94+
# we can't safely divide, so we scale
95+
# the whole row up to compensate
96+
if (((tnum%${denom//-/}) != 0)); then
97+
for((l=0;l<n;++l)); do
98+
((row_i[l]*=denom))
99+
done
100+
denom=1
101+
break
102+
fi
103+
done
104+
for ((j=k+1;j<n;++j)); do
105+
row_i[j]=$((row_i[j]-row_h[j]*num/denom))
106+
done
107+
row_i[k]=0
108+
rows[i]="${row_i[@]}"
109+
done
110+
((h++))
111+
((k++))
64112
fi
65113
done
66-
echo "$min buckets, ${reqs[key]} presses"
114+
115+
# now the fun begins
116+
zero=0
117+
118+
# account for fully zero'd rows
119+
for((i=0;i<m;i++)); do
120+
all_zeroes=yes
121+
for((j=0;j<n;j++)); do
122+
r=(${rows[i]})
123+
[[ ${r[j]} == 0 ]] || all_zeroes=
124+
done
125+
[[ -n $all_zeroes ]] && ((zero++))
126+
done
127+
128+
# calculate remaining free variables
129+
free=$((n-m-1+zero))
130+
if [[ free -le 0 ]]; then
131+
# this puzzle is already solved for us!
132+
ans=0
133+
for((i=0;i<n-1;i++)); do
134+
r=(${rows[i]})
135+
((ans+=r[n-1]/r[i]))
136+
done
137+
((solved++))
138+
((total+=ans))
139+
echo "$ans" > "$cache_key"
140+
else # we have free variables to worry about
141+
echo "Line number: $((idx+1))"
142+
echo "Free: $free"
143+
vardump -r rows
144+
# we need to unfuck the columns
145+
for((i=0;i<n-1;i++)); do
146+
nonzero=0
147+
for((j=0;j<m;j++)); do
148+
r=(${rows[j]})
149+
c=${r[i]}
150+
if [[ $c != 0 ]]; then
151+
((nonzero++))
152+
col=$j
153+
row=$i
154+
fi
155+
done
156+
if [[ $nonzero == 1 ]]; then
157+
if [[ $row -gt $col ]]; then
158+
# uh oh, its fucked
159+
for((j=0;j<m;j++)); do
160+
r=(${rows[j]})
161+
# swaperoo the column-aroo
162+
tmp=${r[row]}
163+
r[row]=${r[col]}
164+
r[col]=${tmp}
165+
rows[j]="${r[@]}"
166+
done
167+
fi
168+
fi
169+
done
170+
vardump -r rows
171+
# find the free variables
172+
free_cols=()
173+
index=0
174+
for((i=0;i<n-1;i++)); do
175+
nonzero=0
176+
for((j=0;j<m;j++)); do
177+
r=(${rows[j]})
178+
c=${r[i]}
179+
[[ $c == 0 ]] || ((nonzero++))
180+
done
181+
if [[ nonzero -gt 1 ]]; then
182+
[[ index -eq 0 ]] && fstart=$i
183+
((free_cols[i]=index++))
184+
fi
185+
done
186+
# find the max req
187+
max=0
188+
for((i=0;i<m;i++)); do
189+
req=${reqs[i]}
190+
[[ req -gt max ]] && max=$req
191+
done
192+
echo MAX: $max
193+
194+
fend=$((fstart+free))
195+
smallest=100000000000
196+
# welcome to hell
197+
for ((p=0;p<=max;++p)); do
198+
for ((x=0;x<=(free==3?p:0);++x)); do
199+
for ((y=0;y<=(free>=2?p-x:0);++y)); do
200+
valid=1
201+
ans=$p
202+
z=$((p-x-y))
203+
guesses=($z $y $x)
204+
for((ro=0;ro<m-zero;ro++)); do
205+
r=(${rows[ro]})
206+
div=${r[ro]}
207+
num=${r[n-1]}
208+
for((co=fstart;co<fend;co++)); do
209+
guess="${guesses[co-fstart]}"
210+
thing=${r[co]}
211+
((num-=guess*thing))
212+
done
213+
# check if num divisible by thing
214+
abs_num=${num//-/}
215+
abs_div=${div//-/}
216+
wtf=${num:0:1}${div:0:1}
217+
wtf=${wtf//[0-9]/}
218+
if [[ $num != 0 && $wtf == '-' ]]; then
219+
valid=
220+
break
221+
fi
222+
if ((abs_num%abs_div != 0)); then
223+
valid=
224+
break
225+
fi
226+
((ans+=num/div))
227+
done
228+
229+
# we should track a min here
230+
if [[ -n $valid && $ans -lt $smallest ]]; then
231+
smallest=$ans
232+
fi
233+
done
234+
done
235+
done
236+
((solved++))
237+
((total+=smallest))
238+
echo "$smallest" > "$cache_key"
239+
fi
67240
done
241+
echo SOLVED: $solved / $idx
242+
echo TOTAL: $total
68243
}
69244

70-
FILE=input.txt
71-
cat $FILE \
72-
| cut -d' ' -f2- \
245+
cat -n "$FILE" \
246+
| tr '\t' ' ' \
247+
| tr -s ' ' \
248+
| cut -d' ' -f2,4- \
73249
| shwoop \
74250
| tr -d '{}()' \
75-
| make_buckets \
76-
| sort -n
251+
| gauss

misc/vardump

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,20 @@
4040
#
4141
# Arguments:
4242
# -v verbose output
43+
# -r make negative numbers red lol
4344
# -C [always|auto|never] when to colorize output, defaults to auto
4445
#
4546
vardump() {
4647
# read arguments
4748
local verbose=false
48-
local whencolor='auto'
49+
local red=false
50+
local whencolor='always'
4951
local OPTIND OPTARG opt
50-
while getopts 'C:v' opt; do
52+
while getopts 'C:v:r' opt; do
5153
case "$opt" in
5254
C) whencolor=$OPTARG;;
5355
v) verbose=true;;
56+
r) red=true;;
5457
*) return 1;;
5558
esac
5659
done
@@ -66,11 +69,13 @@ vardump() {
6669

6770
# optionally load colors
6871
if [[ $whencolor == always ]] || [[ $whencolor == auto && -t 1 ]]; then
72+
local color_red=$'\e[31m'
6973
local color_green=$'\e[32m'
7074
local color_magenta=$'\e[35m'
7175
local color_rst=$'\e[0m'
7276
local color_dim=$'\e[2m'
7377
else
78+
local color_red=''
7479
local color_green=''
7580
local color_magenta=''
7681
local color_rst=''
@@ -171,6 +176,11 @@ vardump() {
171176

172177
# always safely quote the value
173178
value=${value@Q}
179+
if $red; then
180+
while [[ "$value" =~ (.*)-([0-9]+)(.*) ]]; do
181+
value=${BASH_REMATCH[1]}$color_red${BASH_REMATCH[2]}$color_value${BASH_REMATCH[3]}
182+
done
183+
fi
174184

175185
printf ' [%s]=%s\n' \
176186
"${color_key}$key${color_rst}" \

0 commit comments

Comments
 (0)