#AoC 2022 | Day 5 | Solutions & Spoilers
1929 messages ยท Page 2 of 2 (latest)
Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.
Sometimes it's clean okay!!
https://github.com/shenanigansd/scratchpad/blob/main/events/advent_of_code/2022/5/python/script_day5.py#L68
events/advent_of_code/2022/5/python/script_day5.py line 68
*map(int, re.match(r"move (\d+) from (\d+) to (\d+)", instruction).groups())```
^ parse works like this and you get the int conversion for free
yeah I'm sure they use it internally
but that's the thing - they fiddle around with regex so you don't have to
kind of like how Python saves you from having to code from C (unless you decide you want to for AoC puzzles :P )
(@Luna)
At least use Rust BTW!!
alright finished day 5 finally :p
Just got day 5 done too.
Clean as always https://github.com/killjoy1221/aoc22/blob/main/day5.py
looking very nice
nice to see non-golf once in a while :)
zip takes multiple inputs, but that is what that * does for me. zip(*[a,b,c]) the * expands the items into an argument list, so that is the equivalent of zip(a,b,c), when used like that it effectively transposes a 2D array (columns become rows, rows become columns).
why did so many people use regex for parsing?
just doing the following seems so much simpler
amount, _from, _to = [int(word) for word in line.split()[1::2]]
I'm not happy with it but it works
https://paste.pythondiscord.com/yekezizeci
c, f, t = helper.extract_ints(line) ยฏ_(ใ)_/ยฏ
What's wrong with map(int, ptrn.match(line).groups())?
nothing?
I was half tempted to use regex to parse the crates
oh no
Cool one
(?:(?:\[\(d+)\]|( {3})) )+
oh no indeed
If you didnt reformat the input, how did you figure out what letter corresponded to what column? Count the blanks between them?
I ended up hardcoding it XD
The character in position 1 belongs to the first column, the one in pos 4 to the second and so on
yea but that isn't really hardcoding
why not? I had a list that looked like [1, 4, 5...]
I mean, I was using list comprehension to make it but still
I did a range though the number of columsn and got the char at i*3+1
line[1::4]?
Darn, I should've thought of that.
*4, though, right?
checks code
yes.
as a person who likes to implement things from scratch ~~apart from using collections module and parse ~~ i despise aoc helper
but yes, the list slicer was much clever than my slot = index*4+1
is this the channel to ask for help with something regarding Day 5? or would that be better suited for just #advent-of-code
this is the channel
if you want spoilers I guess come in here?
๐
help usually involves spoilers
so I'm trying to parse the "stacks" part of the input into a list of sublists, where each sublist is one "stack" and I am having trouble because for some reason, my code is adding every single crate into the stacks
for example, this is just printing out what should be the first stack, but I am getting this
@opal vine solution discussion so posting here:
don't feel too bad. If you really want, you can always hardcode the stack input in and come back to figuring a way to parse it afterwards
i know discord code blocks are preferred over screenshots, but idk how to also include what I getting as my output. sorry
[[]]*9 won't work
that makes 9 copies references to the same list
try [[] for _ in range(9)]
I did something like this. {int(slot): [] for slot in lines[-1].split()}
thank you so much
Yes, I parsed it backwards
this was giving me such a headache last night that I had to call it quits and go to sleep
i could not for the life of me figure out what was going wrong
i coordinatededed out
I think you missed an -ed
i just did re.findall(r"\d+") lol
coordinatededededed
much better
(ed)*
brother
so whenever I want to make a list of sublists of size N, this is how I should be doing it?
ye
I was doing some cockamamey thing counting spaces before I realized the important value was always in the same column
basically yeah
where my i * 4 + 1 bros at
that was my initial solution, but someone brought up line[1::4] /would also/ work
and I thought it was a bit more elegant
i like going by columns, so i can create each stack at a time
so i didn't slice the line
I'm building my stacks one line at a time in parallel, are you saying you built all of stack 1 then stack 2 and what not?
so you load in all BLAH lines of the input?
yep
I mean, I do too, but I could conceivably rewrite it to only be looking at one line at a time
!e I didn't write this task in python, but this would work
s = \
""" [C] [B] [H]
[W] [D] [J] [Q] [B]
[P] [F] [Z] [F] [B] [L]
[G] [Z] [N] [P] [J] [S] [V]
[Z] [C] [H] [Z] [G] [T] [Z] [C]
[V] [B] [M] [M] [C] [Q] [C] [G] [H]
[S] [V] [L] [D] [F] [F] [G] [L] [F]
[B] [J] [V] [L] [V] [G] [L] [N] [J]
1 2 3 4 5 6 7 8 9 """
print([''.join(x).strip() for x in zip(*(l[1::4] for l in s.splitlines()[-2::-1]))])
@stark pagoda :white_check_mark: Your 3.11 eval job has completed with return code 0.
['BSVZGPW', 'JVBCZF', 'VLMHNZDC', 'LDMZPFJB', 'VFCGJBQH', 'GFQTSLB', 'LGCZV', 'NLG', 'JFHC']
stacks, commands = aoc_lube.fetch(year=2022, day=5).split("\n\n")
stacks = stacks.splitlines()
stacks = [
[stacks[y][x] for y in range(7, -1, -1) if stacks[y][x] != " "]
for x in range(1, 35, 4)
]
shadowed a few times, but this works
What the frick
i feel like there's something cleverer I could do with my crane_operation function
unpacking into zip is infamous way to transpose
so I avoid 2 loops
it's so convenient
does a + (n-1)d count? ๐ญ
def part_one(data):
dictionary = defaultdict(list)
for index, line in enumerate(get_stack_indices(data)):
for items in line:
stack_number = int((items - 1) / 4) + 1
dictionary[stack_number].append(data[index][items])
for key in dictionary.keys():
dictionary[key].reverse()
for line in data:
if "move" in line:
pop_n, source, dest = list(map(int, re.findall("\d+", line)))
for i in range(pop_n):
dictionary[dest].append(dictionary[source].pop())
for key, value in sorted(dictionary.items()):
print(value[-1], end="")
I started reading and got 2021d23 flashbacks
sounds like fragile implementation dependent gray magic to me
oh ok
containers = dict.fromkeys([i for i in range(1, 10)], [])
how is it impl dependent?
from aocd import lines, submit
from collections import defaultdict, deque
from tools import chunks
import re
import pprint
def solve(lines, all_at_once=False):
# Initial setup:
stacks = defaultdict(deque)
it = iter(lines)
for line in it:
if not line:
break
chunked = (
(i + 1, x)
for (i, x) in enumerate(x.strip("[] ") for x in chunks(line, 4))
if x.isalpha()
)
for (i, crate) in chunked:
stacks[i].appendleft(crate)
# Commands:
for line in it:
m = re.search(r"^move (\d+) from (\d+) to (\d+)$", line)
assert m, f"{line} doesn't match"
amount, src, dst = map(int, m.groups())
tmp_stack = []
for _ in range(amount):
tmp_stack.append(stacks[src].pop())
if all_at_once:
tmp_stack = tmp_stack[::-1]
stacks[dst].extend(tmp_stack)
result = "".join(stack[-1] for (i, stack) in sorted(stacks.items()))
return result
submit(solve(lines, False), part="a")
submit(solve(lines, True), part="b")
it's not implementation dependent, it's a little hard to read maybe
I dunno, the zip software is independent of python, isn't it? couldn't they change how it works?
lol, not that zip
i don't know wtf it was about this approach but when i did containers[0].append("1"), it was appending to every single key in the dictionary
no, zip is builtin
There's always zipfile for actual zip archives
had to go with defaultdict
zip iterates over multiple iterables
for real
aaah you discovered
a = []
b = a
a.append(1)
print(b)
!e
print(list(zip('abc', '123', 'ABC')))
@stark pagoda :white_check_mark: Your 3.11 eval job has completed with return code 0.
[('a', '1', 'A'), ('b', '2', 'B'), ('c', '3', 'C')]
huh, ooooh, zipping together two list? not the zip compression format?
import re
input_lines = open("input.txt").read().split("\n")
unparsed_boxes, unparsed_instructions = input_lines[:9], input_lines[10:]
boxes = [""] + ["".join(i).strip()[:-1] for i in zip(*unparsed_boxes)][1::4]
instructions = [[*map(int,re.findall(r"\d+", i))] for i in unparsed_instructions]
for num, origin, destination in instructions:
boxes[destination] = boxes[origin][:num][::-1] + boxes[destination] # remove [::-1] for part 2
boxes[origin] = boxes[origin][num:]
print("".join(s[0] for s in boxes[1:]))
oh shit i was so stuck in parsing hell that i didn't realize that is what i was doing
zip(*iter) life-saver
!e
for a, b, c in zip("cat", "dog", "hat"):
print(a, b, c)
!e
print(list(zip('abc', '123', 'AB')))
@jolly sparrow :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | c d h
002 | a o a
003 | t g t
@iron turtle :white_check_mark: Your 3.11 eval job has completed with return code 0.
[('a', '1', 'A'), ('b', '2', 'B')]
i see a goat in there somewhere
happens
ok, I wanna see a state initializer using zip
a goat is just a dog in a hat
!e ```py
l = ["aA1", "bB2", "cC3"]
print(["".join(i) for i in zip(*l)])
@sleek grail :white_check_mark: Your 3.11 eval job has completed with return code 0.
['abc', 'ABC', '123']
hang on i'm not actually sure if that is what happened, let me redo
my rust code for parsing wasn't terrible
let mut piles: [Vec<_>; 9] = Default::default();
for s in crane.lines().rev().skip(1) {
for (i, &c) in s.into_iter().skip(1).step_by(4).enumerate() {
if c != b' ' {
piles[i].push(c);
}
}
}
```though I'm annoyed that there isn't a nicer way to initialize an array of vectors
๐
oh we can post other lang solutions here?
I think that's fine, AoC is full of people playing with new languages
as you can see
rust do be cool
you can
can i type check if an array only has specific type of elements
๐ฆ
yeah i am trying to solve everything in F#
yup! We're certainly a bit partial to python but any solutions in any lang is fine. We even had one of our mods solve Day 1 in vim
wdym?
!e
dictionary = dict.fromkeys(range(3), [])
print(dictionary)
dictionary[0].append("1")
print(dictionary)
@vocal lichen
@manic cobalt :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | {0: [], 1: [], 2: []}
002 | {0: ['1'], 1: ['1'], 2: ['1']}
why does this happen
alright
as in vimscript or just editing their way to glory?
because you're storing the reference to the list
same reason, the list isn't copied but referenced
great question... let me go find the thing
l = []
temp = l
l.append(1)
# temp is now [1]
oh lord is it because of the []?
my nim parsing just copied python:
let
raw = fetch(2022, 5).split("\n\n").mapIt(it.splitLines)
stacks = collect(for x in 0..8:
collect(for y in 0..7:
let chr = raw[0][7 - y][1 + 4 * x]
if chr != ' ': chr))
commands = collect(for line in raw[1]:
line.scanTuple("move $i from $i to $i"))
I coded a bfs in vim using some regex ๐
well because lists are mutable
I don't know enough about vim, but here's what he sent: #1047739554913865738 message
generally mutable objects get passed around as references
this was a first for me
this will happen
ah, some regex and some vim commands, gotcha
yeah i'm aware of that but dunno how it sneaked by me in dicts
bruh
ah
g=str.split;I='\n';x,y=g(open(0).read(),2*I);j=''.join;exec("d=[' ']+[j(m).strip()for m in zip(*g(x,I))][1::4]\nfor l in g(y,I):a,b,c=map(int,g(l)[1::2]);d[c]=d[b][:a][::%d]+d[c];d[b]=d[b][a:]\nprint(j(*zip(*d)));"*2%(-1,1))```
224 exec
```py
g,j,I=str.split,''.join,'\n'
x,y=g(open(0).read(),2*I)
def f(o):
d=[' ']+[j(m).strip()for m in zip(*g(x,I))][1::4]
for l in g(y,I):a,b,c=map(int,g(l)[1::2]);d[c]=d[b][:a][::o]+d[c];d[b]=d[b][a:]
print(j(*zip(*d)))
f(-1)
f(1)```
227 no exec
lol
c style format string
it's being formatted with %
wait I don't even think you need vim
-1 for part 1, 1 for part 2
I think vscode is enough ๐
...
with open("input.in", "r", encoding="utf-8") as file:
file = file.readlines()
# get amount of stacks without looking at the file b4 and only knowing the file scheme
for index in range(len(file)):
if file[index].split()[0].isnumeric():
temp = index
for i in file[index].split():
containers[i] = []
break
```getting the amount of stacks
when reading the containers from a non full line(line where not every stack has a container) how should i approach assigning the containers to the correct stack
@astral ivy @elfin falcon @tulip kindle
zip only has 1 elt so you can just star it
historically I have had fun hacking together solutions in bash
e.g. day 1 part 1
tr '\n' + | sed 's/+$/\n/;s/++/\n/g' | bc | sort | tail -n1
part 2
tr '\n' + | sed 's/+$/\n/;s/++/\n/g' | bc | sort | tail -n3 | xargs | tr ' ' + | bc
I love me some hacked together bash
just out of curiosity, would python stacks = [[] * 9] work how I want it to? or would that also make 9 references to the same list
The latter
neither
it would be the same as [[]]
because the content of an empty list repeated 9 times is an empty list
is tail equivalent to the tail function usually found in functional programming languages
tail gives the last few lines
thank you ๐
hmm
for layer in range(temp - 1, -1, -1):
for index, char in enumerate(file[layer]):
if index % 2 == 1 and char != " " and char != "\n":
containers[str(index // 4 + 1)].append(char)
```solved
dammit, I get the urge to write some hacky bash for today
yea that was what I originally had
I think you can write the updates as regex
not the whole thing just a small problem
lmao true
@stark pagoda helpfully pointed me in the right direction and told me I should be using python stacks = [[] for _ in range(9)] so I am all good for now thankfully โค๏ธ
containers = {}
with open("input.in", "r", encoding="utf-8") as file:
file = file.readlines()
# get amount of stacks without looking at the file b4 and only knowing the file scheme
for index in range(len(file)):
if file[index].split()[0].isnumeric():
temp = index
for i in file[index].split():
containers[i] = []
break
# assign containers to correct stack in start position
for layer in range(temp - 1, -1, -1):
for index, char in enumerate(file[layer]):
if index % 2 == 1 and char != " " and char != "\n":
containers[str(index // 4 + 1)].append(char)
file = file[temp+2:]
for operation in file:
_, amount, _, prev, _, after = operation.split()
for i in range(int(amount)):
temp = containers[prev].pop()
containers[after].append(temp)
# outputting solution for task 1
for stack in containers:
print(containers[stack][-1], end="")
```part 1 solved
i think i did way too many for loops but its working
NOICE shorter. What did you change tho? ๐ค
on my phone rn. can't compare ๐
exams started ๐ฅฒ ,
from ..aoc import get_input
day_input = get_input(5).strip()
def print_stack(stack):
for i in stack:
print(*i)
print()
stack_raw, movements = day_input.split('\n\n')
stack = []
stack_temp = []
stacks = 8
stack_raw = stack_raw.split('\n')[0:-1]
for i in range(1, len(stack_raw[0]), 4):
stack.append([])
for j in range(stacks):
crate = stack_raw[j][i]
if crate != ' ':
stack[-1].append(crate)
stack[-1] = stack[-1][::-1]
movements = [list(map(int, [j for j in i.split(' ') if j.isnumeric()])) for i in movements.split('\n')]
for movement in movements:
times,from_, to = movement[0], movement[1]-1, movement[2]-1
temp_stack = []
while times > 0 and stack[from_]:
temp_stack.append(stack[from_].pop())
times -= 1
stack[to].extend(temp_stack[::-1])
print(''.join([i[-1] for i in stack if len(i)]))
containers = {}
containers2 = {}
with open("input.in", "r", encoding="utf-8") as file:
file = file.readlines()
# get amount of stacks without looking at the file b4 and only knowing the file scheme
for index in range(len(file)):
if file[index].split()[0].isnumeric():
temp = index
for i in file[index].split():
containers[i] = []
containers2[i] = []
break
# assign containers to correct stack in start position
for layer in range(temp - 1, -1, -1):
for index, char in enumerate(file[layer]):
if index % 2 == 1 and char != " " and char != "\n":
containers[str(index // 4 + 1)].append(char)
containers2[str(index // 4 + 1)].append(char)
file = file[temp+2:]
for operation in file:
_, amount, _, prev, _, after = operation.split()
amount = int(amount)
for i in range(amount):
temp = containers[prev].pop()
containers[after].append(temp)
containers2[after] += containers2[prev][-amount:]
containers2[prev] = containers2[prev][:-amount]
# outputting solution for task 1
for stack in containers:
print(containers[stack][-1], end="")
print()
# output for task 2
for stack in containers2:
print(containers2[stack][-1], end="")
g=str.split;I='\n';x,y=g(open(0).read(),2*I);j=''.join;exec("d=[' ']+[j(g(j(m)))for m in zip(*g(x,I))][1::4]\nfor l in g(y,I):a,b,c=map(int,g(l)[1::2]);d[c]=d[b][:a][::%d]+d[c];d[b]=d[b][a:]\nprint(j(*zip(*d)));"*2%(-1,1))```
222 exec
```py
g,j,I=str.split,''.join,'\n'
x,y=g(open(0).read(),2*I)
def f(o):
d=[' ']+[j(g(j(m)))for m in zip(*g(x,I))][1::4]
for l in g(y,I):a,b,c=map(int,g(l)[1::2]);d[c]=d[b][:a][::o]+d[c];d[b]=d[b][a:]
print(j(*zip(*d)))
f(-1)
f(1)
225 no exec
j(m).strip() -> j(g(j(m)))
so I figured out how to parse my letters, but I need to know first how many lists/deques I need first right? I feel like reading the last number of the 1 2 3 ... 9 would work but it feels wrong?
g=str.split;I='\n';x,y=g(open(0).read(),2*I);j=''.join;exec("d=[I]+[j(g(j(m)))for m in zip(*g(x,I))][1::4]\nfor l in g(y,I):a,b,c=map(int,g(l)[1::2]);d[c]=d[b][:a][::%d]+d[c];d[b]=d[b][a:]\nprint(j(*zip(*d)));"*2%(-1,1))
220 exec
g,j,I=str.split,''.join,'\n'
x,y=g(open(0).read(),2*I)
def f(o):
d=[I]+[j(g(j(m)))for m in zip(*g(x,I))][1::4]
for l in g(y,I):a,b,c=map(int,g(l)[1::2]);d[c]=d[b][:a][::o]+d[c];d[b]=d[b][a:]
print(j(*zip(*d)))
f(-1)
f(1)```
223 no exec
[' '] -> [I]
I used defaultdict(list)
this is how im parsing atm
for d in data:
if d == '':
break
for i in range(len(d) % 4):
if d[i*4+1].isalpha():
print(d[i*4+1], i)
!e
from collections import defaultdict
a = defaultdict(list)
a[1].append(2)
a[2].append(3)
a[1].append(4)
print(a)
@vocal lichen :white_check_mark: Your 3.11 eval job has completed with return code 0.
defaultdict(<class 'list'>, {1: [2, 4], 2: [3]})
For some reason this one felt easier to do without a bunch of weird tricks like set intersection
https://github.com/AM2i9/adventofcode/blob/master/2022/05.py
if by read, you mean read it in programmatically, why would that be wrong?
If by read you mean you will actually just read it with your eyes and hardcode it in, that's not wrong either, you can solve how you want, though I would encourage everyone to do a fully programmatic solution
no i meant hardcode the idea:
"find the line that that contains the indexes of the crates and find the last/largest number" which would be the number of lists you need
feels icky
so the latter of my two comments then. You can solve it however you want.
Well you don't really need that line because you can just dynamically add stacks when needed
For example, there's nothing wrong with hardcoding, solving and coming back to it if you wish
i mean parsing the input sort of implies you've looked at it before --- it's not purely programmatic
Counterpoint: you can solve most(?) days without actually looking at your input, just getting the schema from the problem statement and example input.
indeed it's possible, here is part 2
s="$(for i in {1..9}; do head -n8 $1 | tac | cut -c$((-2 + 4*i)); echo "$i"; done | tr -d '\n ')"
while read line; do
set $line
s="$(echo "$s" | sed -E "s/(.{$2})$4(.*)$6/$4\2\1$6/;s/$6(.*)(.{$2})$4/\2$6\1$4/;")"
done < <(tail -n+11 $1)
echo "$s" | grep -o '.[0-9]' | tr -d '\n0-9'
transposing was probably the most annoying part
otherwise regex for updating is cute
you have to look at some input, be it example or otherwise
I store the letters followed by the number for the pile
ZN1MCD2P3
```that way I can target specific piles when replacing
got this working
crates = defaultdict(list)
for d in data:
if d == '':
break
for i in range(len(d) % 4):
if d[i*4+1].isalpha():
crates[i+1].append(d[i*4+1])
crate[0] will never be used but im just doing that it matches with the later instructions
could also just do i-1 later on
so the example goes
ZN1MCD2P3
ZND1MC2P3
1MC2PZND3
MC12PZND3
M1C2PZND3
if it's a default dict, why even have a [0]
isn't it nice when you think "I think this would technically work" and then it works?
Isn't it depressing when you think it works but it doesn't.
I had that feeling multiple times this morning
Then figuring out you putted the calculation backwards.
But that just makes it feel even better when you do figure it out
My solution today was decent
I like the regexes themselves, with saner names:
s/(.{$count})$src(.*)$dst/$src\2\1$dst/
--------------- ------
pick from src put at dst
s/$dst(.*)(.{$count})$src/\2$dst\1$src/;
--------------- ------
pick from src put at dst
```and I try both variants since I don't know whether src<dst or src>dst
This was my experience with making a BST for my uni coursework, I had about 5 versions that I thought should work that didn't
Thankfully it does work now :)
text = open(r"boxes.txt", "r").read().splitlines()
instructions = open(r"instructions.txt").read().splitlines()
array = [[],[],[],[],[],[],[],[],[]]
charcounter = 0
for line in text:
mainind = 0
spacecounter = 0
for char in line:
if char == " ":
spacecounter += 1
if spacecounter == 4:
mainind += 1
spacecounter = 0
elif char == "[":
spacecounter = 0
elif char == "]":
pass
elif char != "\n":
array[mainind].append(char)
mainind += 1
moveinstructs = []
frominstructs = []
toinstructs = []
for line in instructions:
offset = 0
if line[6] == " ":
moveinstructs.append(line[5])
else:
moveinstructs.append((str(line[5]) + str(line[6])))
offset += 1
frominstructs.append(line[12 + offset])
toinstructs.append(line[17 + offset])
for i in range(len(moveinstructs)):
moveinstructs[i] = int(moveinstructs[i])
for i in range(len(frominstructs)):
frominstructs[i] = int(frominstructs[i])
for i in range(len(toinstructs)):
toinstructs[i] = int(toinstructs[i])
for insnum in range(len(moveinstructs)):
fromcolumn = frominstructs[insnum] - 1
tocolumn = toinstructs[insnum] - 1
numofmoves = moveinstructs[insnum]
for i in range(numofmoves):
boxletter = array[fromcolumn][len(array[fromcolumn])-1]
array[fromcolumn].pop(len(array[fromcolumn])-1)
array[tocolumn].append(boxletter)
total = ""
for i in range(len(array)):
total += array[i][len(array[i]) - 1]
print(total)
why no worky
i just get the wrong answers
the block of code to read the boxes works
and the block of code to read the instructions works
and after blood, sweat and tears i finally managed to get the block of code executing the instructions to not error
but it's saying that it's the wrong answer
anyone know why???
does it work on the test data?
also, consider printing out array to see all the values inside it. it's short.
it's very annoying to get your code working, but from running it I think your piles are the wrong order at the start
you do?
if you reverse them things seem to work
array = [x[::-1] for x in array]
i got cdn for the test
hmm, wonder why that is
i'll try
thx
because you add the crates from top to bottom
ahhhh yea
tru
e
but if you reverse the array won't it just reverse the order of the columns?
or is that not how reversing 2d arrays works
yeah your rows are backwards.
yep
yeah I get the right answer when I reversed each row in your array:
array = [row[::-1] for row in array]
good luck!
I enjoyed today's puzzle ๐ Here is my solution: https://paste.pythondiscord.com/uzimakehic.py
What is the best way to get the numbers from the commands?
I'm currently iterating over every line and check if the character is an int but that gets pretty messy when the number is bigger than 9.
I went with a regular expression: ```py
instruction_pattern = re.compile(r'move (\d+) from (\d) to (\d)')
@tropic crescent
A useful helper function to have is one that extracts all the integers from a string.
Yes, just saw that in your solution. That seems a lot easier, I will try that out thanks a lot.
parse("move {moves:d} from {source:d} to {destination:d}", line) , with the parse lib.. {:d} matches all
!eval ```py
import re
def ints(s: str) -> list[int]:
pattern = re.compile(r'\d+')
return [
int(group)
for group in pattern.findall(s)
]
print(ints('move 1 from 1 to 2'))
@civic yacht :white_check_mark: Your 3.11 eval job has completed with return code 0.
[1, 1, 2]
You can use this for processing the input of many of the problems 
You might also want to have one for floats too.
screw that, split and take every odd index
Oh cool, I've not seen this library before 
Yeah I had to mess around with the numbers a lot the last day, thanks
I found it via /r/adventofcode yesterday ๐
hm idk if re has split but you can just do re.split('\\D+') right
nvm just saw this
It seems really helpful
Definitely going to read up on it for work
Finally I catched up again
from typing import List, Iterator, Dict, Tuple
import re
def get_data() -> Tuple[Dict[int, List[str]], List[List[int]]]:
with open("input.txt", "r") as file:
lines_: Iterator[str] = iter(file.read().split("\n"))
stacks_: Dict[int, List[str]] = dict()
line: str = None
while line != "":
line = next(lines_)
for count, char in enumerate(line):
if char.isalpha():
count = int(count / 4) + 1
if stacks_.get(count):
stacks_.get(count).append(char)
else:
stacks_[count] = [char]
pattern: re.Pattern = re.compile(r'\d+')
commands_ = []
while True:
char: str
try:
line = next(lines_)
commands_.append([int(number) for number in pattern.findall(line)])
except StopIteration:
break
return dict(sorted(stacks_.items())), commands_
def move_crates(reversed_: bool = True) -> str:
stacks: Dict[int, List[str]]
commands: List[List[int]]
stacks, commands = get_data()
for command in commands:
crates = reversed(stacks.get(command[1])[:command[0]]) if reversed_ else stacks.get(command[1])[:command[0]]
stacks.get(command[2])[:0] = crates
stacks[command[1]] = stacks[command[1]][command[0]:]
message: str = ""
for stack in stacks.values():
message += stack[0]
return message
def part_one() -> str:
return move_crates()
def part_two() -> str:
return move_crates(False)
if __name__ == "__main__":
print(part_one())
print(part_two())
My solution for today.
I would appreciate any suggestions
If py >= 3.9 you can use tuple, dict, and list instead of the typing versions
Also the type hint for lines is unnecessary
magic ๐
Your parsing can be simplified a bit
!e You can use for multiple times on an iterator to pick up where you left off after a break
a = [1,2,3,4,5,6,7,8,9]
it = iter(a)
for x in it:
if x == 4:
break
print("first loop", x)
print("Doing other stuff")
for x in it:
print("second loop", x)
@vocal lichen :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | first loop 1
002 | first loop 2
003 | first loop 3
004 | Doing other stuff
005 | second loop 5
006 | second loop 6
007 | second loop 7
008 | second loop 8
009 | second loop 9
Eh wrong @
shield your eyes folks
from collections import defaultdict, deque
import re
with open("crates.txt", "r") as f:
drawings, moves = f.read().split("\n\n")
crates = defaultdict(deque)
for d in drawings.split("\n"):
for i in range(len(d) % 4):
if d[i*4+1].isalpha():
crates[i+1].appendleft(d[i*4+1])
for m in moves.split("\n"):
amount, old, new = list(map(int, re.findall("\d+",m)))
for i in range(amount):
crates[new].append(crates[old].pop())
for crate in crates.values(): print(crate[-1])
That's not terrible
timeout
this works on the demo
but
Traceback (most recent call last):
File "main.py", line 16, in <module>
crates[new].append(crates[old].pop())
IndexError: pop from an empty deque
i would assume all the instructions are valid no?
deque, cute. that'll be important later when they start asking us to scale the answers.
yeah in general with all of AOC input you can assume the input is valid.
so no worries that there is a line to move from 3, to 4, pizza times.
are you sure you'rea accounting for the crates being 1-indexed and not 0-indexed ?
when i add it to the deque I use crates[i+1].appendleft(d[i*4+1]) so it should line up with the move instruction 1:1
ah I see, and crates is a dict. got it
for example on the demo
crates:
defaultdict(<class 'collections.deque'>, {2: deque(['M']), 1: deque(['C']), 3: deque(['P', 'D', 'N', 'Z'])})
try printing you crates to be sure they rotated correctly ?
your crates look to be in reverse order
I was about to ask, that doesn't look like shell stuff ๐
ah,. but it's a dict, nm
hmm, I put a print here
for m in moves.split("\n"):
amount, old, new = list(map(int, re.findall("\d+",m)))
for i in range(amount):
crates[new].append(crates[old].pop())
print(crates[new])
and insta error out, so it must be happening in the very beginning
wait, I only see 3 crates
yes
THERE ARE 9 CRATES - Picard
that's why the demo works, the demo only has 3. the input has 9
Anyone who gets that reference is my kind of person.
i think im missing the point here lol, nothing is hard coded there so the amount of crates shouldnt affect my code?
with open(filename) as f:
drawings, moves = f.read().split("\n\n")
crates = defaultdict(deque)
for d in drawings.split("\n"):
for i in range(len(d) % 4):
if d[i*4+1].isalpha():
crates[i+1].appendleft(d[i*4+1])
print(crates)
only 3 crates.
% vs //
Right, forgot that thanks
Enterprise Editionโข๏ธ refactor: https://paste.pythondiscord.com/ifurerexam.py
my modulo?
yeah
Thanks
length of line % 4 would be the max amount of letters per crate
no?
since its NUM bracket space bracket NUM
or space space space
@vocal lichen :white_check_mark: Your 3.11 eval job has completed with return code 0.
0
for i in range(len(d) // 4 + 1):
this will get you the correct number of crates, which will expose your next issue.
for debugging try this:
for n in range(1,10):
print(n, crates.get(n))
I'm guessing there's more than 0 crates
next issue? 
(insert 5th element 0 stones 0 crates reference)
the hardest part was putting the input boxes into arrays - the actual instructions was just ```py
crates[to].extend(crates[from_][-move:])
crates[from_] = crates[from_][:-move]
1 deque(['T'])
2 deque(['C', 'G', 'N', 'J', 'H', 'P', 'D'])
3 deque(['M', 'G', 'V', 'H', 'G', 'N', 'H', 'F', 'G', 'M', 'W', 'V', 'J', 'L', 'N', 'Z', 'H', 'M', 'M', 'R', 'R', 'S', 'D', 'L', 'G', 'V', 'P', 'B', 'N', 'C'])
4 deque(['N', 'F', 'H'])
5 deque(['M', 'D', 'Z', 'J', 'W', 'F', 'B', 'V'])
6 deque(['B', 'H'])
7 deque(['J'])
8 deque(['V', 'F', 'T'])
9 deque(['G'])
Nothing looks glaringly wrong here
๐ค
Yup. looks like you're getting all 9 crates now.
with the change to the for loop, it parsed correctly on my input too (which is different than your input)
so I get
for crate in crates.values(): print(crate[-1])
THHCVTJGD
which is ... not the answer?
for crate in crates.values(): print(crate[-1])
does not print IN NUMERICAL ORDER.
๐
also, throw a join in there, save yourself some trouble.
print(''.join(crates[n][-1] for n in range(1,10)))
yup. I spent all the time parsing, and no time processing. ๐
for a,b,c in orders:
part1[c].extend([part1[b].pop() for _ in range(a)])
alternatively without hardcoding the number of crates: print(''.join(crate[-1] for (_, crate) in sorted(crates.items())
Thanks for your help @flat mountain I feel like I got 95% there and then just broke down lol
yep - the parsing took me ages but everything else was cake
Parsing the initial crates took me longer than any of the other entire challenges wo far this year ๐คฃ. If only the initial stacks were represented horizontally!
probably quicker, yeah
Oh, this one will be tricky to do as a one-liner. Finally some challenge!
one-liner can only go taht far.
you need to beat 220 chars
a twit?
Tweet*
But we use the real OG Twitter around here
You have to get <140 for that
I mean, one-line python is turing complete right?
Parsing is annoying here, I already parsed first part in one-liner. Functional programming ftw XD
I don't do golfing, just one-liners (mostly list comprehensions/generators etc). :3
Is it? It could be. But not a good way of programming any way.
I mean you have exec and eval so trivially yes
Also you can do lambda calculus so also yes
@tulip kindle any improvements in the golfing?
A couple in the channel I think but I've been busy
same, last I saw 227 without exec. 224 with
220
.
nah we're not at ๐ฏ yet
still 220
๐
There we go, 220
we were at like 390 at one point. 390 => 220 is quite impressive
g,j,I=str.split,''.join,'\n'
x,y=g(open(p).read(),2*I)
for o in -1,1:
d=[I]+[j(g(j(m)))for m in zip(*g(x,I))][1::4]
for l in g(y,I):a,b,c=map(int,g(l)[1::2]);d[c]=d[b][:a][::o]+d[c];d[b]=d[b][a:]
print(j(*zip(*d)))
217 without exec @elfin falcon @tulip kindle
oh damn
hehe
Now these return strings... wtf
def day5(inp: str) -> tuple[str, str]:
did = -1
data = inp.strip().split("\n")
for i, j in enumerate(data):
if j.startswith(" "):
did = i
break
numbe_of_stacks = (len(data[did]) + 1) // 4
stacks = []
for i in range(numbe_of_stacks):
stacks.append([])
for i in range(did - 1, -1, -1):
for i, j in enumerate(data[i][1::4]):
if j != " ":
stacks[i].append(j)
cstacks = list(i[:] for i in stacks)
for i in data[did + 2:]:
print(i)
match i.split(" "):
case "move", a, "from", b, "to", c:
for _ in range(int(a)):
stacks[int(c) - 1].append(stacks[int(b) - 1].pop(-1))
cstacks[int(c) - 1] += cstacks[int(b) - 1][-int(a):]
cstacks[int(b) - 1] = cstacks[int(b) - 1][:-int(a)]
print("moved", a, "from", b, "to", c)
case o:
raise ValueError(o)
ret1 = "".join(i[-1] for i in stacks)
ret2 = "".join(i[-1] for i in cstacks)
return (ret1, ret2)```
did you know? I am a big fan of slicing
haven't tried exec. idk tho
check it once
le part 2
from collections import defaultdict, deque
import re
with open("crates.txt", "r") as f:
drawings, moves = f.read().split("\n\n")
crates = defaultdict(deque)
for d in drawings.split("\n"):
for i in range(len(d) // 4 + 1):
if d[i*4+1].isalpha():
crates[i+1].appendleft(d[i*4+1])
for m in moves.split("\n"):
amount, old, new = list(map(int, re.findall("\d+",m)))
step = len(crates[old]) - amount
crates[old].rotate(-step)
for i in range(amount):
crates[new].append(crates[old].popleft())
print(''.join(crate[-1] for (_, crate) in sorted(crates.items())))
exec has the same # of chars since your change just removed the function calls
not really applicable for the exec solution
yeah, I think it would be more. exec was useful to distribute and exec function twice. Now loop. so no need
yep
time to ```py
print(import("requests").get("https://sussywebsite.py/day5", json = {"data": open("day5", "r").read()}).json())
requests is 3rd party
urllib?
sure ig
SOCKETS?
buw why doe
print(__import__("json").load(__import__("urllib.request").urlopen("..."))
After some research I figured out the deque is the best data structure for this but Idk exactly how to put each stack in a deque
g,j,I=str.split,''.join,'\n'
x,y=g(open(0).read(),2*I)
for o in-1,1:
d=[I]+[j(g(j(m)))for m in zip(*g(x,I))][1::4]
for l in g(y,I):a,b,c=map(int,g(l)[1::2]);d[c]=d[b][:a][::o]+d[c];d[b]=d[b][a:]
print(j(*zip(*d)))```216
Can someone please help me I am stuck?
Python is a security risk because it doesn't come preinstalled with windows.
windows is a security risk so it doesn't matter
lol.
does python have #define like c++? @iron girder
thinking if loop can be #define and used functionally
python does not have pre-processors
Use environment variables instead
๐
maybe i should make python with macros
โ illegal for codegolf
Why use macros when you monkeypatch?
good take
because it's my tool, i get to define "best practice"
macros are best practice, monkeypatch is not
Hey! What help do you require?
It was the best of practices, it was the blurst of practices.
python macros will be blursed
I want to know how to put each stack in a deque
Make it yourself by wrapping your script in exec()
well yes, that's how i intend to make it
OK. How far have you gotten?
Trying to make every line in a list
Then connect each item with it's equivalent in the list under it
when you say every line, do you mean every line in the input file (in the section with the stacks)?
Yeah
So, I'm not sure that you necessarily need every line in a list
only way this gets shorter is if some regexes the entire parser for shorter
For example, you can index directly into the lines as a string. Which can be beneficial as each crate for a stack is in the same position in the line string
i will make you eat those words
maybe
I need to index each one manually right?
That is one approach to it, yes
haha ๐คฃ
you could index in a variety of different ways. I personally did so by getting the indexes from the label row (e.g. 1 2 3) and then using that to index into each row
Can I see your code?
sure. Just note it's the opposite of code golf :)
s=[n:=open("input"),*map(lambda x:[*filter(str.isalpha,x[::-1])],[*zip(*[l[1::4] for l in next(zip(*[n]*10))[:8]])])]
for c,f,t in map(lambda x:[*map(int,x.split()[1::2])],n):
s[t]+=s[f][-c:]
s[f]=s[f][:-c]
[print(i[-1],end="")for i in s[1:]]
found this on reddit (247)
maybe it can give some ideas@iron girder
Wdym by code golf?๐
Others are experts in code golf, not me - maybe they can explain :P
getting the shortest solution possible in characters
^
In contrast, my solutions can be measured in number of classes
three classes today :)
you'll always win in classes
Oh k
class CrateStacks(list[Optional[list[str]]]):
@classmethod
def from_text(cls, stack_txt: str) -> "CrateStacks":
stack_list = reversed(stack_txt.splitlines())
header, stack_contents = next(stack_list), list(stack_list)
assert (
max(int(crate_no) for crate_no in header.strip().split()) <= 9
) # Only a single-digit number of stacks are supported
stack_text_indices = [
(int(ele), idx) for idx, ele in enumerate(header) if ele != " "
]
stacks: list[Optional[list[str]]] = [None] + [[] for _ in stack_text_indices]
for row in stack_contents:
for stack_index, stack_text_index in stack_text_indices:
stack_value = row[stack_text_index]
if stack_value != " ": # found a stack value
stack = stacks[stack_index]
assert stack is not None
stack.append(stack_value)
return cls(stacks)
this is where I do my stack parsing
not characters ๐ bytes
I basically reverse the stack diagram, going from the bottom
yeah, bytes. mb
grab the label row and get the positions of each label
Oh
then work my way up the diagram, indexing into each row and grabbing the crates if they are there
then adding to a list of lists
What is cls?
oh, this is a class method. I did this this way by extending onto the list class
basically, instantiating a list a different way
not important for understanding how to parse the text
stack_list = reversed(stack_txt.splitlines())
header, stack_contents = next(stack_list), list(stack_list)
assert (
max(int(crate_no) for crate_no in header.strip().split()) <= 9
) # Only a single-digit number of stacks are supported
stack_text_indices = [
(int(ele), idx) for idx, ele in enumerate(header) if ele != " "
]
stacks: list[Optional[list[str]]] = [None] + [[] for _ in stack_text_indices]
for row in stack_contents:
for stack_index, stack_text_index in stack_text_indices:
stack_value = row[stack_text_index]
if stack_value != " ": # found a stack value
stack = stacks[stack_index]
assert stack is not None
stack.append(stack_value)
this is all that matters really
Oh k
g,j,I=str.split,''.join,'\n'
f=open(0).readlines()
for o in-1,1:
d=[I]+[j(g(j(m)))for m in zip(*f[:8])][1::4]
for l in f[10:]:a,b,c=map(int,g(l)[1::2]);d[c]=d[b][:a][::o]+d[c];d[b]=d[b][a:]
print(j(*zip(*d)))```
211
What is assert?
also not important
@astral ivy eat those words
it just checks an assumption made about the program
Oh
I've tried to code this in a general way
haha, love it!
but even still, this wouldn't work if there were more than 9 stacks
so I do an assert to ensure that's the case, and raise an exception if it isn't
g,j,I,f=str.split,''.join,'\n',[*open(0)]
for o in-1,1:
d=[I]+[j(g(j(m)))for m in zip(*f[:8])][1::4]
for l in f[10:]:a,b,c=map(int,g(l)[1::2]);d[c]=d[b][:a][::o]+d[c];d[b]=d[b][a:]
print(j(*zip(*d)))```
202
again, totally unnecessary :) I am the anti-golfer
It seems like I need to improve my OOP knowledge but Idk where to read
All what I was redirected for were 2 articles from real python
The Resources page on our website contains a list of hand-selected learning resources that we regularly recommend to both beginners and experts.
I'd say get familiar with the constructs, then have a look at OOP code to see the style it's written in
that said, don't go crazy with OOP
I mostly do composition, and stay away from inheritance, for example
Oh k
(even though the code snippet I posted above was inheritance but ignore that :) )
WTF
*open(0)
never seen that in my life
๐
I saw that alot of people used re is that an easier approach if I learn re
Lol no
Okay, 3 lines instead of 1. I chose to split input separately (can be incorporated into the main part, but that wouldn't be optimal)
And then python complained about walrus in the iterable part, so I had to split that as well
in_s, in_m = map(str.splitlines,in5a.split("\n\n"))
d5a = (s:=[*map(lambda x: [*reversed("".join(x).replace(" ",""))],(zip(*([line[i] for i in range(1, len(in_s[-1]), 4)] for line in in_s[:-1]))))]) + ([[s[int(c)-1].append(s[int(b)-1].pop()) for _ in range(int("".join(a)))] for *a,b,c in ((e for e in line if e.isdigit()) for line in in_m)] and [])
print("".join(e[-1] for e in d5a))
Firstly re isn't "really" going to help you for the stack parsing. It'd be more for the rearrangements
Secondly, there's a quote by a programmer called Jamie Zawinski
I hate myself for the [something_that_returns_none(e) for...] and []
gottta keep riling you up for better solutions then ๐คฃ
best way to get a better solution from me is to beat my solution
Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.
There are other ways to parse text
Oh
String operations is one of them, and generally easier
the golfed solution uses no regex
open(0) == open stdin as file-like
- is for unpacking
So this is quick making a list from stdin
Okay I will check that out
i don't think that's really fair..
parse still uses regex
I would say generally see if you can use operations like .split() before busting out the regex
re.split(" ")
but your current solution will only work for specific input. anything less or more in stack height and it'll fail
yeah I know XD And CPython uses C but now you don't have to use C cos you have Python (unless you are Luna doing AoC)
pretty sure aoc has a stack height of 8 though
ik lol. i just hadn't thought it that way
i checked with multiple accounts, they all had stack heights of 8
so my solution should work for any aoc input
8 for me as well. but just that, it wouldn't be generic
that's all
Parse works like this:
rearrangement_txt = 'move 1 from 2 to 1'
parsed_text = parse.parse(
"move {move:d} from {start:d} to {end:d}", rearrangement_txt
)
print(parsed_text["move"], parsed_text["start"], parsed_text["end"])
a simpler way than re IMO (but still good to know re for when things get complex)
regex was what messed up my code the first few times, since I did move (\d) from (\d) to (\d) and didn't realize that the first number could be two digits
That was one issue
the stack height starts at 8 but it can go above that with the instructions.
someone else did [1-9]+
correct
i'm someone else 
but my golfed code assumes starting height of 8, that's all
it's been a long day, can't remember everyone XD
I also did regex for the stacks, and I somehow got that first try with \[(\S)\][ \n]?| [ \n]?
all I remember were that there were 2 regex boo-boos here
yeah I just thought it was funny xD
yep, else it's good to go
@lilac sand anyhow, is that all good or do you have any further questions about completing today?
what does open(0) do, what is an integer file descriptor
0 := stdin
1 := stdout
2 := stderr
i think that's an OS specific thing though, right?
ahh makes sense, i should've figured. ty
idk lol
i don't have access to a windows machine
so i can't check
let's see..
is *open(x) bad form or something? like not using with
it's considered best practice in code golf
because anything is best practice if it's short ๐
open(0) seems to be stdin at least
๐
good enough lul
yea seems super cool but not widely spread so i'm curious why
because input() is more useful
because in general, reading from stdin is rare
tessa posting a shorter solution? ๐
yea but i mean the unpack with open in general not just for reading from stdin
@iron girderWhat about mapping this part?
[j(g(j(m)))for m in zip(*f[:8])][1::4]
Also j(g(j... feels cringe ngl
no ๐
it's less readable than f.readlines() or f.read().splitlines() and such
pretty common in code golf, it's not used much elsewhere because you need to send an eof
usually people don't send eofs through stdin if it's a command line thing
ok so bad form in the sense of readability
more of a usability issue
people probably don't want to do ctrl + d when running your code
for golfing though, it's fine
ok cool, tyty
nah
[*map(j,map(g,map(j,zip(*f[:8]))))][1::4]```
lambda would also be longer
if there was a way to compose functions without lambda, then maybe
any chance of walrusing the a,b,c line?
what would you walrus
bro
the code works on the exmaple
and doesnt on the actual thing
ima cry myself to sleep
rip
nvm, it won't
the post add is still irking me. there's gotta be a shorter += solution ๐ฉ
like bro what even went wrong there
I'm only seeing one digit numbers, make sure your code can handle moving quantities >= 10
a lot of the things in my code rely on front = top
like the zip
yep
and flipping the order also means we need to use -a instead of a
that would fuck the zip up
i don't remember how many chars zip saved
2 2 8
In the last line 2 is [V, Q, R, L, H] and in the next is [V, Q, R, L], which means it only moved 1
for n, x, y in inst:
stack[y-1].extend([stack[x-1].pop() for _ in range(n)][::-1 if stackmove else 1])```
is there a smarter way to do this
the indexes are 1 too high as im using 0
the line youre thinking about is the previous command
are you sure that the end of the array is the top of each stack?
but what instruction makes [V, Q, R, L, H] become [V, Q, R, L]?
cuz it's using the stacks from the penultimate step
from the what
actually no mb all is fine
well this works
does any1 have like a short example I could test the code on
g,j,I,*f=str.split,''.join,'\n',*open(0)
for o in-1,1:
d=[I]+[j(g(j(m)))for m in zip(*f[:8])][1::4]
for l in f[10:]:a,b,c=map(int,g(l)[1::2]);d[c]=d[b][:a][::o]+d[c];d[b]=d[b][a:]
print(j(*zip(*d)))```
201
g,j,*f=str.split,''.join,*open(0)
for o in-1,1:
d=[I:='\n']+[j(g(j(m)))for m in zip(*f[:8])][1::4]
for l in f[10:]:a,b,c=map(int,g(l)[1::2]);d[c]=d[b][:a][::o]+d[c];d[b]=d[b][a:]
print(j(*zip(*d)))```
200
CMZ
@astral ivy
depends on your notion of legality
compilesโข๏ธ
it compiles
skill issue
ROAD TO SUB 200!
@atomic coyote are you having a problem trying to get your code to work correctly?
yes
i think
yay walrus!
g,j,*f=str.split,''.join,*open(0)
for o in-1,1:
d=['']+[j(g(j(m)))for m in zip(*f[:8])][1::4]
for l in f[10:]:a,b,c=map(int,g(l)[1::2]);d[c]=d[b][:a][::o]+d[c];d[b]=d[b][a:]
print(j(*zip(*d)))
196
we need a walrus emoji
I was completely useless and i didn't realize
would you like to post your code? I can debug it for you if you wish
if you found a way to reduce the number of indexes/make the index code more condense you could get lower
we're sub-200 now
that could be decently hard as its java unfortunately
ah lol
literally was about to comment that
aight
though true story, I once read the opening chapter of a Java book and fell asleep on my bed
this sentence kinda sounds depressive as well lol
LMAO
its not that bad
got into a really deep sleep
๐
can you post the code as text? ain't no way I'm typing that out
just compile in your head
not that hard smh
fair
we went from 6^3 characters to 14^2 character. An achievement ngl
Pasting large amounts of code
If your code is too long to fit in a codeblock in Discord, you can paste your code here:
https://paste.pythondiscord.com/
After pasting your code, save it by clicking the floppy disk icon in the top right, or by typing ctrl + S. After doing that, the URL should change. Copy the URL and post it here so others can see it.
just paste here
parsing too hard
is Z the top crate in the first stack?
Hey @atomic coyote!
You either uploaded a .txt file or entered a message that was too long. Please use our paste bin instead.
!paste
tried to cheat the system kekw
asking sunder
ah ok
no its the bottom one
im going bottom to top
cuz in that case I can use the stack
to peek (get top element), push (slap on top), and pop (remove from top)
you didn't what?
lol
yeah i saw that, was gonna tell you
bro i love parsing code am I right
Oh ty that helps with the last bit
I have a biotechnology competition tmr so I might try to solve this tmr
Tysm
is there a cleaner way for me to combine move_crates() and move_crates_2()? ```python
def parse_raw():
with open('input.txt') as f:
data = f.read().split('\n')
instructions = data[10:-1]
horizontal_stacks = [stack[1::4] for stack in data[:8]]
stacks = [[] for _ in range(9)]
for row in reversed(horizontal_stacks):
for position, crate in enumerate(row):
if crate != ' ':
stacks[position].append(crate)
return stacks, instructions
stacks, instructions = parse_raw()
def move_crates(amount, source, dest):
for _ in range(amount):
dest.append(source.pop())
def move_crates_2(amount, source, dest):
dest.extend(source[-amount:])
del source[-amount:]
def part_one():
stacks = parse_raw()[0]
for instruction in instructions:
amount, source, dest = instruction.split()[1::2]
move_crates(int(amount), stacks[int(source) - 1], stacks[int(dest) - 1])
result = ''.join([stack.pop() for stack in stacks])
print(result)
def part_two():
stacks = parse_raw()[0]
for instruction in instructions:
amount, source, dest = instruction.split()[1::2]
move_crates_2(int(amount), stacks[int(source) - 1], stacks[int(dest) - 1])
result = ''.join([stack.pop() for stack in stacks])
print(result)
part_one()
part_two()
instead of combining them, you could combine part_one and part_two and use move_crates or move_crates_2 as an argument to that function
numpy would get rid of the loops
isnt that a lot of chars to import np
but the import may be a problem
but 2 loops to compensate if they get removed
that is true, but for my own consistecy with previous days i think i want to keep a part_one() and part_two() for each day
you could still do that if you wanted to :)
my code gets worse every day
we started with this and we end with 50 lines of adding stuff to a stack
the part I hate the most is parsing ngl
Once everything is set up, use functools.partial to set part_one() and part_two()
going with that same thought process though, i guess I could do something like ```python
def move_crates(amount, source, dest, part):
if part == 1:
for _ in range(amount):
dest.append(source.pop())
elif part == 2:
dest.extend(source[-amount:])
del source[-amount:]
edited the 196 to use the bs character, this way the space doesn't show up when printing
because np would allow things like ```py
j(g(j(zip(*f[:8]))))[1::4]
instead of
```py
[j(g(j(m)))for m in zip(*f[:8])][1::4]```
would a while loop somehow work for o in-1,1
i doubt, but still
loop break check would be problematic
does np auto allow you to multiply lists etc
yep, under most conditions
-1
d[b]=d[b][a:]
d[b][:a]=[]
err -2 even?
or wait, are these tuples?
str rather
I guess it doesn't work then
ok
just make the code 20 chars
no, it's a different class from actual lists
i don't get what you mean
but created the same way
exec(bytes('โฑงโฑชๆช็ฝ็ด็ฎๆฑฐ็ฉโฌโธงๆฝชๆนฉโจฌ็ฏๆนฅใจเจฉๆฝฆโฒโฏๆนฉใญใฌเจบๆ ๅฌฝเ งๅดงๅฌซโกชโกงโกชโฅญโคฉๆฝฆโฒโญๆนฉ็จ ็ฉโจจๅญฆใ บโฅๅญใจฑใบเฉๆ ็ฏๆฐ ๆค โฎๅญฆใฑๅดบๆบๆฌๆฌๆดฝ็กๆคจ็ฎๆฌๆฐจๅฌฉใจฑใบโฅๆปๆใตๅญคๅตขใฉๅตกใฉๆผบโญๅญคๅตฃๆปๆใตๅญคๅตขๆ
ๅดบโ็ฐๆนฉโกดโกช็จช็ฉโจจโฅคโคฉ','u16')[2:])```
123 chars, close enough
what
Even if you import numpy, you can't do [1,2,3] * [4,5,6]
can u not?
idk how np works
no
yeah really sorry about this, can't do 20 in python ๐
all I know is that I could do [1,2,3] * 2
if it had been a list you could have done the latter
with open() ๐
!e ```py
import numpy as np
print(np.array([1,2,3]) * np.array([4, 5, 6]))
[1,2,3] * [4,5,6]
@vocal lichen :x: Your 3.11 eval job has completed with return code 1.
001 | [ 4 10 18]
002 | Traceback (most recent call last):
003 | File "<string>", line 3, in <module>
004 | TypeError: can't multiply sequence by non-int of type 'list'
i have ni idea how np works
๐คทโโ๏ธ
You should try python. ๐
no you shouldn't
like everything else, it's a tool that takes time to learn the semantics of. Under the hood it's just a very fast array/math library written in C and fortran.
Watching top positions from today taught me that if effort to hardcore input is relatively low it should be chosen over parsing programmatically:)
but 221 bytes, so prev is still better
true
where's the golfing at rn
196
g,j,*f=str.split,''.join,*open(0)
for o in-1,1:
d=['']+[j(g(j(m)))for m in zip(*f[:8])][1::4]
for l in f[10:]:a,b,c=map(int,g(l)[1::2]);d[c]=d[b][:a][::o]+d[c];d[b]=d[b][a:]
print(j(*zip(*d)))```
That was my issue, I decided to be clever and just paste it into a spreadsheet with transpose, and it failed, and then I tried a little something with cut and paste, and that failed, and then finally I programattically did it. I should have just typed it out by hand. there were only 9 words. I spent forever on it. lol. And then like 3 minutes tops doing parts 1 and 2 combined.
I parsed it in python. Took me a while lol
or this (196)
g,j,*f=str.split,''.join,*open(p)
for o in-1,1:
d=['']+[j(g(j(m)))for m in zip(*f[:8])][1::4]
for l in f[10:]:a,b,c=map(int,g(l)[1::2]);d[c],d[b]=d[b][:a][::o]+d[c],d[b][a:]
print(j(*zip(*d)))
like it like that
it's the same thing tbh, just combining assignments
My original working parsing :
data = open(filename).read().splitlines()
part1 = [list(x for x in row if x !=' ')
for row in zip(*data[:8][::-1])
if row[0] not in '[] ']
and the shorter rewrite:
data = open(filename).read().splitlines()
part1 = [list(''.join(r).strip())
for r in zip(*data[:8][::-1])][1:36:4]
wish, if a,b,c & rest could be assigned with it. then it could be possibly converted to list comprehension
This is what I did
def parse_stacks(stacks_input: str) -> list[list[str]]:
"""Parse stacks string input into a list"""
stacks = stacks_input.split("\n")[:-1]
number_of_stacks = len(list(stacks[0])) // 4 + 1
stack_content: list[list[Any]] = [[] for _ in range(number_of_stacks)]
for line in stacks:
stack_line = line[1::4]
for idx, sl in enumerate(stack_line):
if sl != " ":
stack_content[idx].append(sl)
return [list(reversed(s)) for s in stack_content]
I do know python yeah, yall have the job way easier
you could share your code here, I shared mine and it took like 5 seconds for someone to find my bug
what's the 36 about?
probably the length of a row
pandas rocks yet again
d1 = pd.DataFrame(pd.read_csv("day_5.input", nrows=pd.read_csv("day_5.input", sep=" ", engine="python", header=None)[0].str.startswith("[", na=False).argmin(), header=None, squeeze=True).str.replace(r" {4}", " NaN", regex=1).str.replace(r"\[|\]", "", regex=2).str.split().tolist()).T.iloc[:, ::-1].pipe(lambda fr: fr.set_axis(fr.columns[::-1], axis=1)).dropna().agg(list, 1).pipe(lambda fr: fr.set_axis(fr.index + 1)).explode().replace("NaN", pd.NA).dropna().groupby(level=0).agg(list)
print(pd.read_csv("day_5.input", skiprows=pd.read_csv("day_5.input", sep=" ", engine="python", header=None)[0].str.startswith("[", na=False).argmin() + 1, header=None, squeeze=True).str.findall(r"\d+").explode().astype(int).groupby(level=0).agg(list).apply(lambda a: d1[a[-1]].extend(d1[a[1]][-a[0]:][::-1]) or d1[a[1]].__setitem__(slice(-a[0], None), [])).any() or d1.str[-1].pipe(lambda s: s.groupby([0] * len(s))).agg("".join).item())
# Part 2
d2 = pd.DataFrame(pd.read_csv("day_5.input", nrows=pd.read_csv("day_5.input", sep=" ", engine="python", header=None)[0].str.startswith("[", na=False).argmin(), header=None, squeeze=True).str.replace(r" {4}", " NaN", regex=1).str.replace(r"\[|\]", "", regex=2).str.split().tolist()).T.iloc[:, ::-1].pipe(lambda fr: fr.set_axis(fr.columns[::-1], axis=1)).dropna().agg(list, 1).pipe(lambda fr: fr.set_axis(fr.index + 1)).explode().replace("NaN", pd.NA).dropna().groupby(level=0).agg(list)
print(pd.read_csv("day_5.input", skiprows=pd.read_csv("day_5.input", sep=" ", engine="python", header=None)[0].str.startswith("[", na=False).argmin() + 1, header=None, squeeze=True).str.findall(r"\d+").explode().astype(int).groupby(level=0).agg(list).apply(lambda a: d2[a[-1]].extend(d2[a[1]][-a[0]:][::+1]) or d2[a[1]].__setitem__(slice(-a[0], None), [])).any() or d2.str[-1].pipe(lambda s: s.groupby([0] * len(s))).agg("".join).item())
!e
print("[D] [W] [W] [F] [T] [H] [Z] [W] [R]"[1:36:4])
@edgy cypress :white_check_mark: Your 3.11 eval job has completed with return code 0.
DWWFTHZWR
!e
print("[D] [W] [W] [F] [T] [H] [Z] [W] [R]"[1::4])
@iron girder :white_check_mark: Your 3.11 eval job has completed with return code 0.
DWWFTHZWR
don't need the 36 smh
smh
nah, golfs quite well without panda as well
that's not golfing
the way you wrote it looks like golfing
golfing aims smallest bytes, i did not
my aim is to write the thing using only pandas methods
because pure Python is too restrictive in functionality, no fun
and it's pandas with an "s" at the end, other thing is something different :)
I originally had it as a range, where you would need it and it just got carried over while I was swapping.
I tried converting it to processing strings, but the lack of "string pop" seemed to make it worse.
part1[c-1].extend([part1[b-1].pop() for _ in range(a)])
vs
part1[c] += part1[b][:-a-1:-1]
part1[b] = part1[b][:-a]
you failed
print
yeah i should've used .to_csv :)
i don't think you need print. i think pandas has things that can write to files
it can even write to clipboard indeed
i'm doing these in IPython, so i don't even print, but in case someone tries to do in a script, which is super unlikely, i put prints when bringing here.
i mean, that's kinda impressive lol
are you doing part 1 or 2?
not sure if any better when you combine them, but here's part 1 + 2 together:
print((T:=(R:=(I:=__import__)("functools").reduce)(lambda P,L:(R(lambda p,i:((P[0][i+1].append(L[i*4+1]),P[1][i+1].append(L[i*4+1]))if L[i*4]=="["else P,P)[-1],range(len(L)//4),P)if"["in L else((t:=[*map(int,I("re").findall("\d+",L))]),R(lambda *_:P[0][t[2]].insert(0,P[0][t[1]].pop(0)),range(t[0]),0),P:=(P[0],D(list,{**P[1],t[2]:P[1][t[1]][:t[0]]+P[1][t[2]],t[1]:P[1][t[1]][t[0]:]})))[-1]if"move"in L else P),open("input/05.txt"),((D:=I("collections").defaultdict)(list),D(list))),*["".join(x[1][0]for x in sorted(t.items()))for t in T])[-2:])
not strictly, was mostly going for a one-liner, but improvements are welcome
thanks!
can probably also refactor some of the x if a else y to [y,x][a], will get to that at some point
it's just very hard editing this monstrosity without breaking stuff ๐
shortest chars is 123, bytes is 196
g,j,*f=str.split,''.join,*open(0)
for o in-1,1:
d=['']+[j(g(j(m)))for m in zip(*f[:8])][1::4]
for l in f[10:]:a,b,c=map(int,g(l)[1::2]);d[c]=d[b][:a][::o]+d[c];d[b]=d[b][a:]
print(j(*zip(*d)))```
196 bytes
```py
exec(bytes('โฑงโฑชๆช็ฝ็ด็ฎๆฑฐ็ฉโฌโธงๆฝชๆนฉโจฌ็ฏๆนฅใจเจฉๆฝฆโฒโฏๆนฉใญใฌเจบๆ ๅฌฝเ งๅดงๅฌซโกชโกงโกชโฅญโคฉๆฝฆโฒโญๆนฉ็จ ็ฉโจจๅญฆใ บโฅๅญใจฑใบเฉๆ ็ฏๆฐ ๆค โฎๅญฆใฑๅดบๆบๆฌๆฌๆดฝ็กๆคจ็ฎๆฌๆฐจๅฌฉใจฑใบโฅๆปๆใตๅญคๅตขใฉๅตกใฉๆผบโญๅญคๅตฃๆปๆใตๅญคๅตขๆ
ๅดบโ็ฐๆนฉโกดโกช็จช็ฉโจจโฅคโคฉ','u16')[2:])```
123 chars
wow
have you tried gzipping
I am coding in JS using Functional Programming
This was so time-consuming
5-1: ```js
.split("\n\n").reduce((a,c)=>[[a,c]]).map(e=>[e[0],...e[1].trim().split("\n").map(f=>[1,3,5].map(g=>+f.split(' ')[g]))])[0].reduce((a,c,i,)=>i==0?Array(+c.trim().split("\n").map(e=>e.split(' ')).pop().pop()).fill().map((,j)=>c.split('\n').slice(0,-1).map(e=>[...e].filter((e,k)=>(k-1)%4==0)[j]).filter(e=>e!=' ')):a.map((e,j,a)=>j==c[1]-1?e.slice(c[0]):j==c[2]-1?[...a[c[1]-1].slice(0,c[0]).reverse(),...e]:e),0).map(e=>e[0]).join("")
5-2: ```js
.split("\n\n").reduce((a,c)=>[[a,c]]).map(e=>[e[0],...e[1].trim().split("\n").map(f=>[1,3,5].map(g=>+f.split(' ')[g]))])[0].reduce((a,c,i,_)=>i==0?Array(+c.trim().split("\n").map(e=>e.split(' ')).pop().pop()).fill().map((_,j)=>c.split('\n').slice(0,-1).map(e=>[...e].filter((e,k)=>(k-1)%4==0)[j]).filter(e=>e!=' ')):a.map((e,j,a)=>j==c[1]-1?e.slice(c[0]):j==c[2]-1?[...a[c[1]-1].slice(0,c[0]),...e]:e),0).map(e=>e[0]).join("")
I'm glad the second was the same as the first just without the .reverse(), but still... wow... so easy to make mistakes
what are you guys zipping again?
most readable i could cook was
import re
from collections import defaultdict, deque
def helper(data):
stacks = defaultdict(deque)
instructions = []
for index, line in enumerate(data):
crate_positions = [(m.span()[0] + 1) for m in re.finditer("\[[a-zA-Z]\]", line)]
if crate_positions:
for crate_position in crate_positions:
stacks[crate_position // 4].append(line[crate_position])
else:
if line:
instructions.append(list(map(int, re.findall("\d+", line))))
instructions = instructions[1:]
return (dict(sorted(stacks.items())), instructions)
def part_one(data):
stacks, instructions = helper(data)
for pop_n, source, dest in instructions:
for _ in range(pop_n):
stacks[dest - 1].appendleft(stacks[source - 1].popleft())
return "".join([stack[0] for stack in stacks.values()])
def part_two(data):
stacks, instructions = helper(data)
for pop_n, source, dest in instructions:
poppers = deque()
for _ in range(pop_n):
poppers.appendleft(stacks[source - 1].popleft())
stacks[dest - 1].extendleft(poppers)
return "".join([stack[0] for stack in stacks.values()])
@molten hamlet
def get_stack_indices(data):
indicies = []
for line in data:
indexes = [index for index, char in enumerate(line) if char.isalpha()]
if not indexes:
break
indicies.append(indexes)
return indicies
def part_one(data):
dictionary = defaultdict(list)
for index, line in enumerate(get_stack_indices(data)):
for items in line:
stack_number = int((items - 1) / 4) + 1
dictionary[stack_number].append(data[index][items])
for key in dictionary.keys():
dictionary[key].reverse()
for line in data:
if "move" in line:
pop_n, source, dest = list(map(int, re.findall("\d+", line)))
for i in range(pop_n):
dictionary[dest].append(dictionary[source].pop())
for key, value in sorted(dictionary.items()):
print(value[-1], end="")
print()
def part_two(data):
dictionary = defaultdict(list)
for index, line in enumerate(get_stack_indices(data)):
for items in line:
stack_number = int((items - 1) / 4) + 1
dictionary[stack_number].append(data[index][items])
for key in dictionary.keys():
dictionary[key].reverse()
for line in data:
if "move" in line:
pop_n, source, dest = list(map(int, re.findall("\d+", line)))
lst = []
for i in range(pop_n):
lst.append(dictionary[source].pop())
lst.reverse()
dictionary[dest].extend(lst)
for key, value in sorted(dictionary.items()):
print(value[-1], end="")
oh no
zip is already gzipped.
What the?
| exec(bytes
day 5 looks hard
Truthfully, the parsing can be tricky but once it is parsed it is relatively simple
And even then you can just hardcode to begin with if you struggle, and then come back to parse the input afterwards
time to brush up my regex skills
Honestly if you are talking about the stack parsing piece I wouldnโt suggest regex if you are struggling
# aoc problem 5
import re
def getinput():
stacks = []
moves = []
with open('5.txt') as f:
acc = []
part = 0
for line in f:
match part:
case 0:
slots = [line[i+1] for i in range(0, len(line), 4)]
try:
int(slots[0])
except ValueError:
acc.append(slots)
else:
for stack in zip(*acc):
stacks.append([s for s in stack[::-1] if s != ' '])
part += 1
case 1:
part += 1
case 2:
m = re.fullmatch(r'move (\d+) from (\d) to (\d)\n?', line)
depth, orig_num, dest_num = map(int, m.groups())
moves.append((depth, orig_num - 1, dest_num - 1))
return stacks, moves
def rearrange(depth, orig, dest):
for i in range(depth):
dest.append(orig.pop())
def rearrange2(depth, orig, dest):
dest.extend(orig[-depth:])
for i in range(depth):
orig.pop()
def rearrangement_process(function, stack, moves):
for m in moves:
depth, orig_i, dest_i = m
function(depth, stack[orig_i], stack[dest_i])
def main():
stacks, moves = getinput()
stacks1 = [s.copy() for s in stacks]
rearrangement_process(rearrange, stacks1, moves)
print(*(s[-1] for s in stacks1), sep='') # part 1 solution
stacks2 = [s.copy() for s in stacks]
rearrangement_process(rearrange2, stacks2, moves)
print(*(s[-1] for s in stacks2), sep='') # part 2 solution
if __name__ == '__main__':
main()
My solution: ```py
from string import digits
import numpy as np
def chunked_between(iterable, chunk_size: int, between_size: int):
in_between = False
curr_chunk_size = chunk_size
chunk_step = 0
chunk = []
for item in iterable:
chunk.append(item)
chunk_step += 1
if curr_chunk_size == chunk_step:
if not in_between:
yield chunk
chunk = []
in_between = not in_between
curr_chunk_size = between_size if in_between else chunk_size
chunk_step = 0
with open('5.txt') as f:
text = f.read().strip('\n')
lineiter = iter(text.split('\n'))
lines = []
for line in lineiter:
if line[:3] == ' 1 ':
next(lineiter)
break
curr_line = []
for chunk in chunked_between(line, 3, 1):
char = chunk[1]
if char == ' ':
char = None
curr_line.append(char)
lines.append(curr_line)
stacks = [
list(
filter(
lambda x: x is not None,
reversed(stack)
))
for stack
in np.array(lines).transpose()
]
moves = []
for line in lineiter:
move = []
num = ''
for char in line:
if char == ' ' and num:
move.append(int(num))
num = ''
elif char in digits:
num += char
if num:
move.append(int(num))
moves.append(move)
moves = ((num, orig - 1, dest - 1) for num, orig, dest in moves)
for num, orig, dest in moves:
orig = stacks[orig]
dest = stacks[dest]
print(orig, dest)
items = orig[-num:]
del orig[-num:]
dest.extend(reversed(items)) # remove reversed for part 2
print(orig, dest)
print(''.join(stack[-1] for stack in stacks))
It uses some pretty dumb and unnecessary things, but it works
Took me a second, but here's my solution
import re
from collections import defaultdict
def partOne():
for line in open('input.txt'):
if '[' in line:
for i in range(1, len(line) - 1, 4):
if line[i] != ' ':
stacks[(i - 1) // 4].append(line[i])
elif line.startswith('move'):
a, b, c = map(int, re.findall(r'\d+', line))
stacks[c - 1] = stacks[b - 1][:a][::-1] + stacks[c - 1]
stacks[b - 1] = stacks[b - 1][a:]
print(''.join(stacks[i][0] for i in range(len(stacks))))
def partTwo():
for line in open('input.txt'):
if '[' in line:
for i in range(1, len(line) - 1, 4):
if line[i] != ' ':
stacks[(i - 1) // 4].append(line[i])
elif line.startswith('move'):
a, b, c = map(int, re.findall(r'\d+', line))
stacks[c - 1] = stacks[b - 1][:a] + stacks[c - 1]
stacks[b - 1] = stacks[b - 1][a:]
print(''.join(stacks[i][0] for i in range(len(stacks))))
stacks = defaultdict(list)
Wow, that's short
nice
anyone got any slight hint on parsing the inputs into stacks?
you might just need to change your point of view
wdym
how much of a hint do you want?
(this is a hint)
i love how that hint makes sense if you already know what it means but is completely unhelpful if you dont
@smoky hinge
g,j,*f=str.split,''.join,*open(0)
for o in-1,1:
d=['']+[j(g(j(m)))for m in zip(*f[:8])][1::4]
for l in f[10:]:a,b,c=map(int,g(l)[1::2]);d[c],d[b]=d[b][:a][::o]+d[c],d[b][a:]
print(j(*zip(*d)))
d5 if you wanna improve it lol
haha, yeah ๐
whoo, time finally freed up
time for 6 and 7 >.>
the parsing was more tedious than the solution, I found
Hey @lunar fox!
It looks like you tried to attach a Python file - please use a code-pasting service such as https://paste.pythondiscord.com
does anyone see anything wrong with this?
https://paste.pythondiscord.com/lazazikuma
im losing my mind, i just cant figure out what could possibly be wrong - code works for the test case, when i use print statements to debug the sequence of steps my script takes, it looks totally fine, but plugging the end result into AOC doesnt work.
i doubt i will get a response but anything is appreciated thanks
(L40) .index() will return the position of the first instance of the block so if you have more than one of the same letter in the stack it won't delete the correct one
.pop() by itself will already remove the last item for you and return the result so ||boxSelected = stackSelected.pop()|| will be fine
i am now feeling very, very silly
very appreciated seriously i spent way too long on that
I seem to be getting an error on that nvm fixed
for l in f[10:]:a,b,c=map(int,g(l)[1::2]);d[c],d[b]=d[b][:a][::o]+d[c],d[b][a:]
~^^^
IndexError: list index out of range
did you replace the backspace with a space
I have to do that?
or is there a newline at the end
maybe not if it doesn't affect the code
no trailing newlines
doesn't help
seems like it's only reading the first 6 stacks
nvm its my ide stripping trailing whitespace
when I save the input file
yep it works fine
get rid of g = str.split and use .split() instead
j,*f=''.join,*open(0)
for o in-1,1:
d=['']+[j(j(m).split())for m in zip(*f[:8])][1::4]
for l in f[10:]:a,b,c=map(int,l.split()[1::2]);d[c],d[b]=d[b][:a][::o]+d[c],d[b][a:]
print(j(*zip(*d)))
```195
I don't think I'll get that below 188 though
is this just a challenge for getting an accurate solution in the smallest number of characters?
the readability plummets lmfao
guys, how should I get each vertical line for the crates?
Hi, a bit late with this one- I have wrote the following code but it outputs the wrong answer. I tried to use a debugger tool but didn't get really far, can someone help me?
with open("input.txt", "r") as file:
stacks, instructions = file.read().split("\n\n")
instructions = instructions.split("\n")
stacks = stacks.replace("[", " ").replace("]", " ").split("\n")
for i in range(len(stacks)):
stacks[i] = [stacks[i][n : n + 4] for n in range(0, len(stacks[i]), 4)]
stacks = stacks[:-1][::-1]
_stacks = []
for i in range(len(stacks)):
_stacks.append(
list(filter(None, [stacks[n][i].strip() for n in range(0, len(stacks))]))
)
for _ in _stacks:
print(_)
for instruction in instructions:
amount, stack, new_stack = (
instruction.replace("move", "")
.replace("from", "")
.replace("to", "")
.split()
)
amount, stack, new_stack = int(amount), int(stack), int(new_stack)
crates = _stacks[stack - 1][len(_stacks[stack - 1]) - amount :]
for crate in crates[::-1]:
_stacks[stack - 1].remove(crate)
if new_stack - 1 not in _stacks:
_stacks.append([])
_stacks[new_stack - 1].append(crate)
top_crates = []
for stack in _stacks:
if stack == []:
continue
top_crates.append(stack[::-1][0])
print("Part 1:", "".join(top_crates))
Are you sure you're reading the input correctly?
Ah I see the problem
You can't use .remove to get the crates from the stack because you can have multiple of the same numbered crates in the same stack

