#AoC 2022 | Day 3 | Solutions & Spoilers

1 messages · Page 2 of 1

sand jungle
#

@hoary parcel what is the shortest till now?

proud hamlet
#
lines = open("../inputs/day3.txt").read().splitlines()

lines = [lines[n:n+3] for n in range(0, len(lines), 3)]

indexes = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
print(sum(indexes.index(list(set(group[0]).intersection(set(group[1]).intersection(set(group[2]))))[0]) for group in lines))
#

not great but ¯_(ツ)_/¯

sand jungle
hoary parcel
sand jungle
hoary parcel
#

use the LF one

sand jungle
hoary parcel
#

does it give the same wrong answer

sand jungle
#

Weird...

hoary parcel
hoary parcel
sand jungle
#

What does that mean? I mean , how do I do that?

hoary parcel
hoary parcel
sand jungle
#

I-

#

I changed nothing and ran the LF again and it worked

#

WTH

chilly linden
#

todays discovery was for first_elf, second_elf, third_elf in zip(*[iter(data)] * 3): magical

wintry depot
#

indeed ... thanks to stackoverflow I found that as well

chilly linden
#

last night you didn't want to enter the esoteric python territory, what is this today 😭

lethal spindle
#

i did it in lua, I miss Sets sad

chilly linden
#

very neat

#

when i first saw the question i thought it was gonna be hard, turned out to be surprisingly ez

wintry depot
#

Yeah didn't seem easy at first, but now it looks quite simple. But still took me about 30 minutes the 2nd part

quiet heath
#

I thought part 2 was going to be difficult in particular. Was surprised it was almost exactly the same as part 1, just with slightly altered input

wintry depot
#

I can't wait for the next puzzles. Hope I get further than last year, before I lose motivation

fallen sinew
#
d3a = sum(ord(e.lower())-ord('a')+1+26*e.isupper() for line in in3a.splitlines() for e in set(line[:len(line)//2])&set(line[len(line)//2:]))

in3b = in3a.splitlines()
d3b = sum(ord(e.lower())-ord('a')+1+26*e.isupper() for x,y,z in (in3b[i:i+3] for i in range(0,len(in3b),3)) for e in set(x)&set(y)&set(z))

One liners (for second task, I only did splitlines separately because it would look ugly and repeat it many times) on phone :3

chilly linden
ornate linden
#
import string 
  
 scores = {letter: score for score, letter in enumerate(string.ascii_letters, 1)} 
  
  
 def split_strings(row): 
     lenstr = len(row) // 2 
     return row[:lenstr], row[lenstr:] 
  
  
 def intersections(*tups): 
     tups = iter(tups) 
     first = set(next(tups)) 
     for tup in tups: 
         first &= set(tup) 
     return first.pop() 
  
  
 with open("puzzle.input"as f: 
     print( 
         "part1:", 
         sum(scores[intersections(*tup)] for tup in map(split_strings, f.readlines())), 
     ) 
  
  
 with open("puzzle.input"as f: 
     lines = [line.strip() for line in f.readlines()] 
     zipped = zip(lines[::3], lines[1::3], lines[2::3]) 
     print( 
         "part2:", 
         sum(scores[intersections(*tup)] for tup in zipped), 
     )
woeful phoenix
#

ahh ord() I knew there had to be a function that converted strings to ints. I just used a list.

chilly linden
#

woah

mighty robin
#
with open("inputs/input_3.txt", "r") as input_file:
    inputs = [line.strip() for line in input_file.readlines()]

PRIORITIES = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"


def part_one(input):
    total_sum = 0
    for i in inputs:
        comp_one, comp_two = set(i[0 : len(i) // 2]), set(i[len(i) // 2 : len(i)])
        intersection = comp_one.intersection(comp_two)
        total_sum += PRIORITIES.index(list(intersection)[0]) + 1
    print(total_sum)


def part_two(input):
    total_sum = 0
    elf_groups = [input[i : i + 3] for i in range(0, len(input), 3)]
    set_elfs = [[set(k) for k in i] for i in elf_groups]
    for i in set_elfs:
        intersection = i[0].intersection(i[1], i[2])
        total_sum += PRIORITIES.index(list(intersection)[0]) + 1
    print(total_sum)


part_one(inputs)
part_two(inputs)
#

Any suggestions on how to clean part_two?

elf_groups = [input[i : i + 3] for i in range(0, len(input), 3)]
set_elfs = [[set(k) for k in i] for i in elf_groups]

Here I just divide into groups first and then turn each element of the groups into sets, but I feel like there is a better way haha

frigid hawk
mighty robin
naive bridge
#

""" Day 3 Part 1 Solution """

f = open("puzzle_input.txt", "r")
puzzle_input = f.read()

priority_sum = 0
priority_value = lambda it: ord(it) - (96 if(ord(it) in range(ord('a'), ord('z')+1)) else 38)

for line in puzzle_input.split("\n"):
    middle = int(len(line)/2)
    first = line[:middle]
    second = line[middle:]

    for item in second:
        if item in first:
            priority_sum += priority_value(item)
            break           

print(priority_sum) # 7863


""" Day 3 Part 2 Solution """
import functools

f = open("puzzle_input.txt", "r")
puzzle_input = f.read()
puzzle_input_lines = puzzle_input.split("\n")

priority_sum = 0
team_size = 3
priority_value = lambda it: ord(it) - (96 if(ord(it) in range(ord('a'), ord('z')+1)) else 38)

for lineidx in  range(0, len(puzzle_input_lines), team_size):
    
    elf_team = [puzzle_input_lines[lineidx+i] for i in range(team_size)]
    team_item = functools.reduce(lambda x,y: set(x) & set(y), elf_team)
    priority_sum += priority_value(team_item.pop())

print(priority_sum) # 2488

frigid hawk
regal harness
#

🥴 meanwhile me:

hasty moon
#
import os
file_path = os.path.realpath(os.path.dirname(__file__)) + "/input.txt"

def get_priority(char):
    return ord(char) - 64 + 26 if char.isupper() else ord(char) - 96

def part_1(lines):
    def get_points(bag):
        m = len(bag) // 2
        return get_priority(*set(bag[:m]).intersection(set(bag[m:])))
    
    ans = 0
    for line in lines:
        ans += get_points(line)
    return ans

def part_2(lines):
    def get_points(lines):
        return get_priority(*set.intersection(*map(set, lines)))
    
    ans = 0
    for i in range(0, len(lines) - 2, 3):
        ans += get_points(lines[i:i+3])
    return ans

lines = open(file_path).read().strip().split('\n')
print(part_1(lines))
print(part_2(lines))
mighty robin
naive bridge
#

xD

regal harness
frigid hawk
regal harness
#

i ended up not using numpy by default because it actually does take 0.3s to import

warm oracle
#

a&b&c for a,b,c in zip(*[iter(pzl)] * 3) is there a nice way to convert to sets during the zip as well?

frigid hawk
#

I feel like there is a nicer way of doing this but im pretty happy with what I have: ```py
import sys
import os
import string

Get Data

with open(os.path.dirname(sys.argv[0]) + "/input.txt", 'r') as f:
data = f.read()
data = data.split('\n')

Pt 1

priorities = []
for d in data:
splitpoint = int(len(d) / 2)
a = d[:splitpoint]
b = d[splitpoint:]
for i in a:
if i in b:
priorities.append(string.ascii_letters.index(i) + 1)
break

print(sum(priorities))

hasty moon
#

show me the shortest code and the most over engineered code

regal harness
#

yup, you can check yourself via python -X importtime the_script.py 2>importtime_profile, and then showing that file with tuna

mighty robin
#

Huh, will do

quiet heath
hallow vapor
#
from pathlib import Path
data = Path("input.txt").read_text().strip().split("\n")

def priority(item: str) -> int:
    return ord(item) - 96 + 58*(ord(item) < 97)

def part1():
    total = 0
    for racksack in data:
        middle = len(racksack) // 2
        common_letter = (set(racksack[:middle]) & set(racksack[middle:])).pop()
        total += priority(common_letter)
    print(total)

def part2():
    total = 0
    for i in range(0, len(data), 3):
        common_letter = (set(data[i]) & set(data[i+1]) & set(data[i+2])).pop()
        total += priority(common_letter)
    print(total)
frigid hawk
warm oracle
#
sum((a & b & c).pop() for a, b, c in zip(*[iter(map(set, pzl))]*3))```
alright I like this
spring tinsel
#

If anything, I like how AoC brings the absolute garbage outta everyone's code

#

Been long since I last wrote nested listcomp, and fuck yea I'm gonna write more of that stuff

warm oracle
#

both ways, the quick and dirty + the unreadable 1 lines

hallow vapor
frigid hawk
hallow vapor
#

You need to look through the string every time with index

#

The time difference is negligible probably but still

frigid hawk
#

Ah right, while ord() + some maths is quicker?

hallow vapor
#

that's my guess, didn't measure

warm oracle
#

ord(literal) should be converted to int on execution

mighty robin
#

It is never worth to do math

#

Mentally at least

dark fjord
#

There are people that make equations to solve it.

frigid hawk
hallow vapor
#

yeah didn't expect it to be significant, the string is pretty small after all

dark fjord
#

!d timeit

broken condorBOT
#

Source code: Lib/timeit.py

This module provides a simple way to time small bits of Python code. It has both a Command-Line Interface as well as a callable one. It avoids a number of common traps for measuring execution times. See also Tim Peters’ introduction to the “Algorithms” chapter in the second edition of Python Cookbook, published by O’Reilly.

frigid hawk
#

I dont like timeit to be honest

tropic quarry
#

is it possible to use time.time for an entire python file and not a one line

frigid hawk
#

I dont see why not?

ornate linden
#

You could also time it from the commandline. Use time on linux or get-history on powershell

tropic quarry
#

im getting an error when i try subtract t1-t0

frigid hawk
#

You risk timing things you dont want to doing that though

ornate linden
#

True, like interpreter startup

frigid hawk
#

I use this decorator: ```py
def timeit(func):
@functools.wraps(func)
def new_func(*args, **kwargs):
start_time = time.time()
for i in range(100_000_000):
result = func(*args, **kwargs)
elapsed_time = time.time() - start_time
print('function [{}] finished in {} ms'.format(
func.name, int(elapsed_time * 1_000)))
return result
return new_func

#

Which i named timeit to make it super not confusing

ornate linden
#

Use time.perfcounter instead. Its got better resolution

#

Time.perfcounter_ns gives it in nanoseconds

tropic quarry
#

time.time_ns() also gives nanoseconds idk what the difference is

wraith gulch
#
#1 
p = lambda x: ord(x) - 64 + 26 if x.isupper() else ord(x) - 96
g = lambda l: p(*set(l[:len(l) // 2]).intersection(set(l[len(l) // 2:])))
s = lambda k: sum(g(o) for o in k)
print(s(open("input.txt").read().split("\n")))

#2
p = lambda x: ord(x) - 64 + 26 if x.isupper() else ord(x) - 96
g = lambda l: p(*set.intersection(*map(set, l)))
s = lambda k: sum(g(k[i:i+3]) for i in range(0, len(k) - 2, 3))
print(s(open("input.txt").read().split("\n")))
proper barn
#

It all depends on your cpu clock anway

wraith gulch
proper barn
#

I think the question setting is done in python

#

with the 'a' and 'A' portions hmm

ornate linden
#

Perf counter is made for checking how long things take. Time.time is meant for lower resolution timing

frigid hawk
#

I switched it out for the perf_counter but its no different in actual performance

ornate linden
#

Probably because you're doing 100mn runs of the function. If you were running it once it would make more of a difference

frigid hawk
#

Just doing it once can get you wildly varying results though

#

always best to average out over a longer run

hallow vapor
#

what's wrong with timeit?

frigid hawk
#

nothing functionally, just find the interface to it annoying

#

I find the decorator quicker and easier to understand

north night
#
print("Part 1 : ", sum([ord(min(n))-96 if min(n).islower() else ord(min(n))-38 for n in [set(l[:len(l)//2]).intersection(l[len(l)//2:]) for l in [n.rstrip() for n in open("input.txt").readlines()]]]))
print("Part 2 : ", sum([ord(min(n))-96 if min(n).islower() else ord(min(n))-38 for n in [''.join(set([n.rstrip() for n in open("input.txt").readlines()][i]).intersection([n.rstrip() for n in open("input.txt").readlines()][i+1]).intersection([n.rstrip() for n in open("input.txt").readlines()][i+2])) for i in range(0,len([n.rstrip() for n in open("input.txt").readlines()]), 3)]]))
proper barn
#

unreadable

nimble pagoda
#

these one liners doesn't really optimize your code

proper barn
#

they optimize for unreadability

nimble pagoda
#

naive approach written in one line

nimble pagoda
frigid hawk
#

Optimise for smallest screen space

nimble pagoda
#

screen space crisis

coarse trail
#
def part_1(data):
    priority = 0

    for line in data:
        half = len(line) // 2
        r = (set(line[:half]) & set(line[half:])).pop()
        priority += ord(r) - 96 if ord(r) >= 97 else ord(r) - 38

    return priority


def part_2(data):
    priority = 0

    for group in data:
        r = (set(group[0]) & set(group[1]) & set(group[2])).pop()
        priority += ord(r) - 96 if ord(r) >= 97 else ord(r) - 38

    return priority

I use utility functions to load in the data, for part 2 I used a chunking loader, which basically just uses more-itertools.chunked to get the groups of 3.

chilly linden
coarse trail
#

I did consider checking for isupper but I quite liked sticking with ord() 😄

#

I have across this zip(*[iter(data)] * 3) before. I should write it down for times where more-itertools isn't available

chilly linden
#
def part_one(data):
    total = 0
    for sack in data:
        split_index = len(sack) // 2
        first_half, second_half = sack[:split_index], sack[split_index:]
        common = "".join(set(first_half) & (set(second_half)))
        if common.isupper():
            total += ord(common) - 38
        else:
            total += ord(common) - 97 + 1
    return total


def part_two(data):
    total = 0
    for first_elf, second_elf, third_elf in zip(*[iter(data)] * 3):
        common = "".join(set(first_elf) & set(second_elf) & set(third_elf))
        if common.isupper():
            total += ord(common) - 38
        else:
            total += ord(common) - 97 + 1
    return total
#

i love how python makes these things a breeze, absolutely love it

zinc wing
#

I used string.ascii_letters.index(letter)+1 :P

chilly linden
zinc wing
#

!e

import string
print(string.ascii_letters.index("a")+1)
broken condorBOT
#

@zinc wing :white_check_mark: Your 3.11 eval job has completed with return code 0.

1
zinc wing
#

@chilly linden

karmic crow
#

I deliberately went with alphabet.lower() + alphabet.upper() as I think it's a bit more explicit. It doesn't require any special knowledge about string.ascii_letters to understand. E.g. the fact that lowercase letters come before uppercase (which is the kind of thing I would forget lemon_sweat ).

analog mulch
#

@karmic crow

karmic crow
#

Don't have the energy to write one-liners at the moment 😓

analog mulch
karmic crow
#

¯_(ツ)_/¯

chilly linden
maiden lava
hallow vapor
still magnet
#

that's a elegant one liner py_guido

naive bridge
quiet heath
naive bridge
#

Understood, thanks!

frail schooner
#

Or even then the inputs shouldn't be pushed to repo?

#

I wanna make it public later on

quiet heath
frail schooner
#

Okay, gotcha.

night egret
#

Hi

unique pivot
#

In that case, I should probably remove the inputs from my repo

cursive sail
#

it's best to just gitignore them

coarse trail
#

Hmm. Odd reasoning. And if they're bothered they should have this on the site, not some random Reddit post.

quiet heath
coarse trail
#

Well it's sure fire way to make sure everyone doesn't know and commits them. I have. For years. As I was none the wiser.

full scarab
#

A 1-liner for part one but in three lines.```py
def day_3():
f = open("2022/day_3.txt", "r").read().splitlines()
c = [
(((ord(p) - 96) if p.islower() else (ord(p) - 38)) if p.isalpha() else 0) for q in
[[v if v in i[len(i) // 2:] else "0" for v in i[:len(i) // 2]] for i in f]
for p in set(q)
]

print(sum(c)) # PART 1
random mango
#

So i may be completely out of my zone about this 😓

quiet heath
random mango
#

But its been like 3 years now, and i can find nothing of the sort 😓

wise rose
#

oh dang, I need to update my gitignore then

#
def parse_group(sacks):
    sack0 = set(sacks[0])
    sack1 = set(sacks[1])
    sack2 = set(sacks[2])
    for item in sack0:
        if item in sack1 and item in sack2:
            print(item)
            return item

def score_item(letter):
    ord_val = ord(letter)
    if ord_val>96:
        return ord_val-96
    return ord_val-64+26

if __name__ == '__main__':
    total_score = 0
    group_size = 3
    group = []
    with open('input.txt', 'r') as sacks:
        for line in sacks:
            sack = line.rstrip()
            group.append(sack)
            if len(group) < group_size:
                continue
            duped_item = parse_group(group)
            total_score+= score_item(duped_item)
            group = []
    print(total_score)
#

hrmm, code highlighting not happening

random mango
#

But i find the reasoning good. I have seen seed crackers in minecraft, so i understand the worry.

frail schooner
#

for python colors

frail schooner
# wise rose ``` def parse_group(sacks): sack0 = set(sacks[0]) sack1 = set(sacks[1]) ...
def parse_group(sacks):
    sack0 = set(sacks[0])
    sack1 = set(sacks[1])
    sack2 = set(sacks[2])
    for item in sack0:
        if item in sack1 and item in sack2:
            print(item)
            return item

def score_item(letter):
    ord_val = ord(letter)
    if ord_val>96:
        return ord_val-96
    return ord_val-64+26

if __name__ == '__main__':
    total_score = 0
    group_size = 3
    group = []
    with open('input.txt', 'r') as sacks:
        for line in sacks:
            sack = line.rstrip()
            group.append(sack)
            if len(group) < group_size:
                continue
            duped_item = parse_group(group)
            total_score+= score_item(duped_item)
            group = []
    print(total_score)
wise rose
frail schooner
wise rose
#

am I violating some group norms, I'm noticing a lot of people are trying for one liners?

frail schooner
#

no they are doing code golfs

#

trying to get the shortest solutions possible

#

in terms of number of characters used in the file

quiet heath
wise rose
#

:nods: I'm familiar with the concept

frail schooner
#

Its not a group norm, so no worries

wise rose
#

my background values clarity as well as brevity

frail schooner
#

you can solve the stuff however you want

wise rose
#

I could probably tweak my parse_sacks to use a list comprehension though, i try for generality in the main body, but then it's kind of hard coded to groups of size 3 in the parser

quiet heath
frail schooner
naive oriole
#

Last night a huge group of ~9 ish people all collaborating made the solutions that are pinned

#
# LF (144)
*z,=open(0,'rb');u=sum;print(u((u({*a[(l:=len(a)//2):]}&{*a[:l]})-96)%58for a in z),u((u({*b}&{*c}&{*d})-106)%58for b,c,d in zip(*3*[iter(z)])))
# CR (144)
*z,=open(0,'rb');u=sum;print(u((u({*a[(l:=len(a)//2):]}&{*a[:l]})-96)%58for a in z),u((u({*b}&{*c}&{*d})-109)%58for b,c,d in zip(*3*[iter(z)])))
# CRLF (146)
*z,=open(0,'rb');u=sum;print(u((u({*a[(l:=len(a)//2-1):]}&{*a[:l]})-96)%58for a in z),u((u({*b}&{*c}&{*d})-119)%58for b,c,d in zip(*3*[iter(z)])))
# xplatform (156)
z=open(0,'rb').read().split();u=sum;print(u((u({*a[(l:=len(a)//2):]}&{*a[:l]})-96)%58for a in z),u((u({*b}&{*c}&{*d})-96)%58for b,c,d in zip(*3*[iter(z)])))
# xplatform one loop (161)
u=sum;print(u(u((u({*a[(l:=len(a)//2):]}&{*a[:l]})-96)%58for a in(b,c,d))+(u({*b}&{*c}&{*d})-96)%58*1j for b,c,d in zip(*3*[iter(open(0,'rb').read().split())])))
unique pivot
#

If i had fluid in my mouth it would have been all over my monitor right now

frail schooner
#

lol

naive oriole
#

What's kind of funny is that it got so golfed that there were different versions for different platforms

#

because the newline style is different

unique pivot
#

lmao

quiet heath
#

CR only is quite funny. Isn’t that the old Mac OS before X that used to do that?

frail schooner
#

is there like a full form for CR and LF and CRLF?

naive oriole
naive oriole
#

technically it's not an operator

frail schooner
#

I am saving this in my personal Discord for safekeeping

naive oriole
#

*x, = list = x = list[:-1]
iirc

#

so you just remove the last elem

unique pivot
#

ah, I see, a kind of unpacking

naive oriole
#

It's equivalent to saying

frail schooner
#

wait so *x, means all the elements except the last on in x?

naive oriole
#

yeah

frail schooner
#

lol thats hilarious xD

#

never knew that

naive oriole
#

*x, _ = list
_ = last element
*x = everything else

naive bridge
frail schooner
#

wait so to do x = list[:-2] we do *x, , = list? or is there like a different way?

naive oriole
#

you have to do

#

*x,_,=list but yeah

analog mulch
naive oriole
#

,= basically means discard last elem

frail schooner
#

okay, I thought maybe there was a way to do like *x, 2*y = list or something

#

its basically like regex, ig? like if I think in terms of regex, I get it

upper tundra
#

after just finishing day 3, i now feel really stupid for not just doing python values = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' and index() + 1 to get the priority levels

frail schooner
#

xD

#

in hindsight most of us were being obtuse

naive oriole
#

unsure if it's good

#

but hopefully it explains it

upper tundra
#

i made this whole function thinking i was being so smart ```python
def prio(char):
if char.islower():
return ord(char) - 96
else:
return ord(char) - 38

naive bridge
unique pivot
naive oriole
#

The shortest calculation was a hacky math one: (x-96)%58

#

where x = ord(character)

upper tundra
#

wow thats really nice

#

good to know about the string.ascii_lettrs as well

naive oriole
#

Artemis, hsop, cereal, cefqrn, tesseract, jenna, salt-die, indie, and xelf

#

were everyone who helped

#

with the golfing

#

I think

upper tundra
#

shoutout to them

naive oriole
#

I'm probably missing some

#

I was also helping

upper tundra
#

at the very least, im still happy I learned a little bit of new stuff today

#

with the ord() function

wise rose
frail schooner
#

like the if else?

#

no, the list would have lesser lines, it just getting the index

wise rose
#

index() is linear, while ord is constant? admittedly small n, but principle of the thing

naive oriole
#

Actually we ended up doing a hacky solution and ignored ord by reading in "rb" (binary mode) to get the characters as binary numbers (what ord would return)

#

so we skipped the conversion entirely

#

O(0)

frail schooner
#

yeah or just call as rb

wise rose
frail schooner
#

I just did everything the hard way, I have no clue how I finished in about 8 minutes considering I was using the wrong index for the second half of the lines while splitting them for like the first 5 minutes..

wise rose
#

I wonder when I'll be writing test cases for my helper functions...

frail schooner
#

helper functions?

frail schooner
#

for the negative values iirc

naive oriole
#

Yeah it's because it ends up being negative

upper tundra
naive oriole
#

and then you do the %58 to get it correct

wise rose
# frail schooner helper functions?

like my parse_group or score_item functions, when will they be doing complicated enough things I'll want to verify they work on simpler cases

upper tundra
#

the first return statement is not guaranteed to always trigger

#

oh wait

#

i think i know what u mean nvm

wise rose
full scarab
#

Oh, so with %58 you wouldn't have to do -38 on the lowercase ones?

upper tundra
wise rose
#

I dunno, I just habitually try to early-return to avoid indentation as much as possible

naive oriole
frail schooner
#

wait aah I didnt change it back to public while removing the data files

full scarab
frail schooner
#

sec

naive oriole
frail schooner
#

can you try now?

frail schooner
naive oriole
#

!e ```py
print(ord("A")-96)
print((ord("A")-96)%58)

broken condorBOT
#

@naive oriole :white_check_mark: Your 3.11 eval job has completed with return code 0.

001 | -31
002 | 27
frail schooner
#

it returns negative cuz in ASCII uppercase comes before lowercase

naive oriole
#

the computation is cross-platform

#

ord("A") is platform-consistent

frail schooner
#

so uppercase has lower value than lowercase

naive oriole
#

!e ```py
print(ord("a")-96)
print((ord("a")-96)%58)

broken condorBOT
#

@naive oriole :white_check_mark: Your 3.11 eval job has completed with return code 0.

001 | 1
002 | 1
frail schooner
#

or wait am I saying it the opposite way..

#

!e print(ord('a'), ord('A'))

broken condorBOT
#

@frail schooner :white_check_mark: Your 3.11 eval job has completed with return code 0.

97 65
frail schooner
#

okay I was right

dark fjord
frail schooner
naive oriole
#

!e ```py
for a in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ":
print(ord(a)-96,(ord(a)-96)%58)

broken condorBOT
#

@naive oriole :white_check_mark: Your 3.11 eval job has completed with return code 0.

001 | 1 1
002 | 2 2
003 | 3 3
004 | 4 4
005 | 5 5
006 | 6 6
007 | 7 7
008 | 8 8
009 | 9 9
010 | 10 10
011 | 11 11
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/befifafamu.txt?noredirect

full scarab
#

ord("a")-96 and ord("A")-38 works for me, where should I use the %58?

frail schooner
#

my brain just thinks there will be an issue so I did that

full scarab
#
def day_3():
    f = open("2022/day_3.txt", "r").read().splitlines()
    c = [
        (((ord(p) - 96) if p.islower() else (ord(p) - 38)) if p.isalpha() else 0) for q in 
        [[v if v in i[len(i) // 2:] else "0" for v in i[:len(i) // 2]] for i in f]
        for p in set(q)
    ]

    print(sum(c)) # PART 1
dark fjord
#

I'm also using ord-38

naive oriole
naive oriole
#

and it will demonstrate what is happening

frail schooner
#
(ord(p) - 96) if p.islower() else (ord(p) - 38)) if p.isalpha()
#

youre using this so you can replace it with (ord(p)-96)%58

#

wait.. else 0?

dark fjord
#

This my part 1 solution ```py
print(sum([ord(x) - 96 if x.islower() else ord(x) - 38 for r in data for x in set(r[:int(len(r) / 2)]) if x in set(r[int(len(r) / 2): len(r)])]))

full scarab
#

Doing 0 doesn't effect the sum.

frail schooner
#

true

#

just else the other case, ig

unique pivot
#

One thing I was worndering is this is how I split the lines into groups of three, is there a way I could have done this in the forloop without having to have that second list comp?

sacks = input.splitlines()
for i in range(0, len(sacks), 3):
    group = [set(s) for s in sacks[i:i+3]]
naive oriole
#
ord(x) - 96 if x.islower() else ord(x) - 38
# Is equivalent to:
(ord(x)-96)%58
full scarab
#

That's quite cool ngl.

dark fjord
unique pivot
#

I guess, but then I have to loop over that comp

#

I was imagining that there was something like

for group in something(sacks):
naive oriole
#

There was some version of that

#

that we came up with when golfing

#

I don't know exactly what it was

#

you can try and find it

frail schooner
#

would for a, b, c in range(0, len(data), 3) work?

frail schooner
#

or do you need the zip thing?

dark fjord
#

Who knew I'd learn something on day =< 3 :3

frail schooner
#

nope doesnt work

naive oriole
#

Honestly I should compile a list of code golfing tips for python

#

I would just have to find them all

frail schooner
wise rose
#

one thing I've been trying to is to parse the inputs as streams rather than loading it all into memory at once, am I actually doing that?

frail schooner
#

I think they used open(0,'rb') to read directly from stdin

wise rose
#

but like,

if __name__ == '__main__':
    total_score = 0
    group_size = 3
    group = []
    with open('input.txt', 'r') as sacks:
        for line in sacks:
            sack = line.rstrip()
            group.append(sack)
            if len(group) < group_size:
                continue
            duped_item = parse_group(group)
            total_score+= score_item(duped_item)
            group = []
    print(total_score)
#

is line 5 doing that?

#

my mental model of how iterators work is lacking

frail schooner
#

line 5 is just opening the input.txt file in read mode

#

if you want to parse the input from stdin, then I think you use open(0,'r')

naive oriole
#

I'm still finding more code golf tips

frail schooner
#

wait @naive oriole with the stdin open() thing, do you just run the code and then paste the input data in the terminal?

#

the program is just exiting for me

naive oriole
#

Yeah you paste it I think

frail schooner
#

would it work in any terminal? for example vscode?

naive oriole
#

Not sure actually

#

Other people were doing more of the testing

#

I was mainly just looking for more techniques

frail schooner
#
z=open(0,'r')
#

should this work?

#

in python?

#

or *z?

#

oh .read()..

north creek
#

My attempt to part 1:

sum(ord((c:=({*s[:(l:=len(s)//2)]}&{*s[l:]}).pop()).lower())-96+26*(c<'a')for s in I.strip().split())
#

101 character

frail schooner
#

aah only part 1

north creek
#

didnt read part 2 yet, wait a bit

frail schooner
#

aah

naive oriole
#

The part 1 section of the code:

*z,=open(0,'rb');u=sum;print(u((u({*a[(l:=len(a)//2):]}&{*a[:l]})-96)%58for a in z))
#

not sure how many chars

frail schooner
#

85

naive oriole
#

also I might have mismatched parentheses

#

in that one

frail schooner
#

no, it has no errors

naive oriole
#

good

frail schooner
#

as far as vscode is concerned

grave vapor
#

it took me almost an hour for part 2 (including me eating lunch) bc i didn't read it properly 😭

#

thought it said that we had to split it in half

#

not in groups of 3

unique pivot
#

rip

grave vapor
#

here's my solution for part 2 tho

@submit(2, 2022, 3, test=True, submit=False, parser=part_two_parser)
def part_two(daily_input):
    """Solution for AOC Day 3 Part 2."""
    return sum([ 
calculate_priority(set(batch[0]).intersection(set(batch[1])).intersection(set(batch[2])).pop())
        for batch in daily_input
    ])
#

oh that's formatted weirdly

north creek
naive oriole
#

with the command

#

it would be shorter too

dark fjord
#

I'm still thinking if my solution could be shorter ```py
print(sum([(ord(x)-96)%58 for r in data for x in set(r[:int(len(r) / 2)]) if x in set(r[int(len(r) / 2): len(r)])]))

naive oriole
#

you would have to also add [:-1] because of the ,= I think

#

so it would still be ~85 chars

#

but one line

north creek
#
# Part 1: 93 chars
sum(ord((c:=({*s[:(l:=len(s)//2)]}&{*s[l:]}).pop()).lower())-96+26*(c<'a')for s in I.split())
# Part 2: 97 chars
sum(ord((d:=({*a}&{*b}&{*c}).pop()).lower())-96+26*(d<'a')for a,b,c in zip(*[iter(I.split())]*3))
lilac atlas
#

pandas keeps rocking

m = pd.Index([*pd._testing._random.string.ascii_letters]).to_series().pipe(lambda s: s.groupby(s, sort=0).ngroup().add(1))

# Part 1
print(pd.read_csv("day_3.input", header=None, squeeze=True).pipe(lambda s: s.apply(list).explode().groupby(pd.RangeIndex(len(s)*2).repeat(s.str.len().floordiv(2).repeat(2)))).agg("".join).groupby(lambda idx: idx // 2).agg(list).apply(pd.Series).agg(lambda r: next(iter({*r[0]}.intersection(r[1]))), 1).map(m).sum())

# Part 2
print(pd.read_csv("day_3.input", header=None, squeeze=True).groupby(lambda idx: idx // 3).agg(list).apply(pd.Series).assign(**{"3": lambda fr: fr.iloc[:, :2].agg(lambda r: {*r[0]} & {*r[1]}, 1)}).rename(columns=int).agg(lambda r: next(iter({*r[2]} & r[3])), 1).map(m).sum())
lilac atlas
#

who needs import string when i can do pd._testing._random.string

lyric folio
#

lol

broken condorBOT
#

Hey @naive oriole!

You either uploaded a .txt file or entered a message that was too long. Please use our paste bin instead.

naive oriole
frail schooner
naive oriole
#

Yeah I'm probably missing some tips, and just keep in mind that sometimes these will not be shorter (there are always exceptions)

naive bridge
naive oriole
#

Replace int(len(r) / 2) with len(r)//2, it does the same thing

naive bridge
#

true

#

so this:

print(sum([(ord(x)-96)%58 for r in data for x in set(r[:len(r) // 2]) if x in set(r[len(r) // 2:])]))
naive oriole
#

yeah

#

if you want to start golfing that you would start by using :=

naive bridge
#

yup thought about that

naive oriole
#

because you then don't need to calculate len(r) // 2 twice

naive bridge
#

exactly

frail schooner
#

is there a way to do something like print(x:= a for a in [0,1,2])?

#

like reduce for loop and printing the elements one by one into one line?

naive oriole
#

print(*(0,1,2))

#

or better yet

#

print(*"012")

#

equivalent to doing

#

print("0", "1", "2")

frail schooner
#

oh shit

naive oriole
#

if you need them each on their own line

#

it is going to be longer

frail schooner
#

sep='\n'?

naive oriole
#

yeah

#

but still longer

#

or

#

print("0\n1\n2")

#

is probably shortest

frail schooner
#

print(*data,sep='\n') I just did this?

naive oriole
#

that would prob work

frail schooner
#

aah okay

naive oriole
#

unless '\n'.join(data) is shorter but it looks longer

frail schooner
#

okay so again this * is just taken as a value in data without even having to iterate over it?

#

hmm..

naive oriole
#

print(*data) = print(data[0], data[1] ... data[-1])

#

each element is an argument

frail schooner
naive oriole
#

also true

#

but join is longer anyways I thinl

frail schooner
#

by 1 char

#

yeah

#
print(*data,sep='\n')
print('\n'.join(data))
naive oriole
#

the real best answer would be if you shorten your variable name

frail schooner
#

true

#
print(*data*5)``` is weird af
naive oriole
#
n='\n'
p=print
p(*d,sep=n)
p(n.join(d))
frail schooner
#

just prints the contents 5 times

naive oriole
#

yeah its a multiplication and an unpacking

#

so it looks really weird

frail schooner
#

how would I do like each entry multiplied by 5?

naive oriole
#

hmm

#

you mean like
print(5*x for x in l)?

frail schooner
#

without the [x]

#

just x*5

naive oriole
#

oh ok

#

hm

#

it might have to just be that comprehension

#

and we can't use 5for because it could be 5f or or 5 for

#

although it might work in previous versions

oak estuary
#

My solution seems to skip a line if there are two consecutive matches 😭

frail schooner
#

two consecutive matches?

oak estuary
#

So my list is 299 when there's 300 characters

#

For for part A

#

For if there's a match of B for one line and another match of B on the second line, it skips it

frail schooner
#

did you check the number of lines in your data file?

oak estuary
#

Yes

#

It's 300

frail schooner
#

and the sum list has 299 entries?

oak estuary
#

Yep

frail schooner
#

can you send whatever conditional statements youre using?

oak estuary
#

Sure

#
from string import ascii_lowercase, ascii_uppercase

file = open('day_3.txt', encoding="utf-8")
last_i = None
counter = 0


stuff = []
for line in file.readlines():
    line = line.strip('\n')
    reference = int(len(n)/2)
    part_a = line[:reference]
    part_b = b[reference:]
    print([art_a, part_b)
    for i in part_a:
        for it in part_b:
            if i == it and last_i != i:
                stuff.append(i)
                last_i = i



table = [None]
for digit in ascii_lowercase:
    table.append(digit)

for digit1 in ascii_uppercase:
    table.append(digit1)

print(stuff)

for item in stuff:
    counter += table.index(item)
    if table.index(item) == -1:
        raise TypeError

print(counter)
file.close()
#

I should have probably used with but oh well (for file handling)

dark fjord
#

Doesn't really matter if your program stops in 20ms anyways

wise rose
frail schooner
#

b[reference:]?

oak estuary
#

Splits it in half

wise rose
oak estuary
#

odd choice yeah

frail schooner
#

no, what is the b list?

#

it should be line[reference:] no?

oak estuary
#

that's copied weirdly

dark fjord
#

Could someone maybe explain // rq?

oak estuary
#

yes it should be

eternal cipher
#

Divide x by y and round down to next whole number

wise rose
#

as opposed to running the result through int?

frail schooner
#

// is floor division, it rounds down the result of / to the lowest integer value possible with rounding

#

so 9.6 result would give 9

#

instead of 10

wise rose
#

probably a bit more performant since it's staying in the same type the whole time

#

doesn't it come from bit shifting?

frail schooner
#

it does

eternal cipher
#

Oopsone sec

frail schooner
#

@oak estuary is it just me or is that another issue?

oak estuary
#

let me send an updated one, the variable names were a little confusing if I was going to share it

#
from string import ascii_lowercase, ascii_uppercase

file = open('day_3.txt', encoding="utf-8")
last_i = None
counter = 0


stuff = []
for line in file.readlines():
    line = line.strip('\n')
    reference = len(line)//2
    part_a = line[:reference]
    part_b = line[reference:]
    print(part_a, part_b)
    for i in part_a:
        for it in part_b:
            if i == it and last_i != i:
                stuff.append(i)
                last_i = i



table = [None]
for digit in ascii_lowercase:
    table.append(digit)

for digit1 in ascii_uppercase:
    table.append(digit1)

print(stuff)

for item in stuff:
    counter += table.index(item)
    if table.index(item) == -1:
        raise TypeError

print(counter)
file.close()
#

there

frail schooner
#

also dont use this

dark fjord
#

Is there also a ceil operator then?

frail schooner
#

use ```py
part_a&part_b

frail schooner
frail sparrow
#

!d math.ceil

broken condorBOT
#

math.ceil(x)```
Return the ceiling of *x*, the smallest integer greater than or equal to *x*. If *x* is not a float, delegates to [`x.__ceil__`](https://docs.python.org/3/reference/datamodel.html#object.__ceil__ "object.__ceil__"), which should return an [`Integral`](https://docs.python.org/3/library/numbers.html#numbers.Integral "numbers.Integral") value.
eternal cipher
#

math.ceil but dont use that

#

You'll get floating point errors for some numbers

#

Use -(a // -b)

frail schooner
#
set(part_a) & set(part_b)
eternal cipher
#

!e

a = 21
b = 8
print(-(a // -b))
frail schooner
#

to get the intersection

broken condorBOT
#

@eternal cipher :white_check_mark: Your 3.11 eval job has completed with return code 0.

3
wise rose
eternal cipher
frail schooner
#

!e print(set([1, 2, 3]&set([2,3,4]))

#

eh?

oak estuary
#

!e print(set([1, 2, 3]&set([2,3,4])))

broken condorBOT
#

@oak estuary :x: Your 3.11 eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 1, in <module>
003 | TypeError: unsupported operand type(s) for &: 'list' and 'set'
oak estuary
#

hmm

frail schooner
#

aah

oak estuary
#

oh

frail schooner
#

!e print(set([1, 2, 3])&set([2,3,4]))

#

ffs

wise rose
#

roller coaster

frail schooner
#

!e print(set([1, 2, 3])&set([2,3,4]))

broken condorBOT
#

@frail schooner :white_check_mark: Your 3.11 eval job has completed with return code 0.

{2, 3}
frail schooner
#

xD

#

it gives the common elements in both the sets

#

there's unions, intersections, etc.

wise rose
#

ok, why not use &? or the .intersection() method?

#

I suppose you can't do an early escape because we know from context that there'll only be one item

frail schooner
#

with .intersection() you would have to write lots of .intersections if you wanted to do more than two at a time

wise rose
#

so there's some performance left on the table

frail schooner
#

but with set(a)&set(b)&set(c)

#

its a single line to get the intersection between all the sets you want

broken condorBOT
wise rose
frail schooner
#

no I said use &

wise rose
#

"dont use this"

#

?

frail schooner
wise rose
#

eff, am I more tired than I realize?

#

oh, ok

frail schooner
#

set takes unique values and then you can do the intersection

full scarab
#

part 1:

# priority = letters.index(LETTER) + 1
letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
total_priority = 0

with open("input.txt", "r", encoding="UTF-8") as f:
    for line in f:
        line = line.replace("\n", "")
        half_len = int(len(line) / 2)
        compartment_1, compartment_2 = set(line[:half_len]), set(line[half_len:])

        total_priority += letters.index(list(compartment_1.intersection(compartment_2))[0]) + 1

print(total_priority)```
part 2:
```py
# priority = letters.index(LETTER) + 1
letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
total_priority = 0
buffer = []

with open("input.txt", "r", encoding="UTF-8") as f:
    for count, line in enumerate(f):
        line = line.replace("\n", "")
        count += 1

        buffer.append(line)

        if count % 3 == 0:
            total_priority += letters.index(list(set(buffer[0]) & set(buffer[1]) & set(buffer[2]))[0]) + 1
            buffer = []

print(total_priority)    
#

anything that could be shortened/simplified?

frail schooner
#

why are you doing encoding?

#

just as a precaution?

full scarab
frail schooner
#

no worries

frail schooner
hallow vapor
#

int(len(line) / 2) -> len(line) // 2

full scarab
wise rose
#

I personally would put list(compartment_1.intersection(compartment_2))[0] on it's own line just for readability

frail schooner
hallow vapor
#

intersection can be done with &

full scarab
#

is pylint activated? lol

frail schooner
#

yep

full scarab
frail schooner
#

also you can ignore pylint errors per line if you want

full scarab
#

is there a difference or preference between & or .intersection apart from readability?

frail schooner
#

& can be used with multiple sets

#

and is shorter

full scarab
#

yeah had to use that for part 2

#

well it's probably good practice to specify encoding + i'm used to specifying it anyway 🤷‍♂️

hallow vapor
#

Also assigning to two variables two unrelated values is pretty meh

#

I would assign to two variables in the same line only if it was something like unpacking

frail schooner
#

@full scarab use to ignore the error on the line

full scarab
eternal cipher
#

My message just sent like 20 mins late

frail schooner
#

xD

#

Man I really should go to sleep.. its 1:20AM..

#

but I really wanna sit here and try new things xD

full scarab
#

but sadly it releases at 4 am for me so can't compete

frail schooner
#

rip

#

thankfully its like 10:30AM release for me so its all good

full scarab
#

!e

a = [1,2]
print(len(a) / 2)
broken condorBOT
#

@full scarab :white_check_mark: Your 3.11 eval job has completed with return code 0.

1.0
full scarab
#

like what

oak estuary
#

I found out what happened, it's skipping a "B"

frail schooner
#

and why is it doing that?

wanton arrow
#

it's more about clarity than shortness. Also as we are indexing the list the extra chars would ruin the indexes.

oak estuary
#

I think its how I coded it

frail schooner
#

ah okay

oak estuary
#

the B matches are consecutive

#

but obviously my logic was to ensure that each line has a unique match - I obviously coded it wrong the first time

frail schooner
#

I think you made everything a little more complicated than was needed xD

oak estuary
#

Yeah 😂

#

thank you!

frail schooner
#

since you already have the uppercase and lowercase lists

oak estuary
#

Hoepfully part 2 is more straightforward

hallow vapor
frail schooner
#

you could've just used the indexes to get the values

full scarab
frail schooner
#

not you, was talking to mesub

#

I will ping you when I reply to you xD

#

wrong emoji..

hallow vapor
full scarab
frail schooner
#

isnt there like a string callable for the whole list of alphabets?

#

thats seems like a missed opportunity

real musk
#

!e

from string import ascii_letters
print(ascii_letters)```
#

wait

full scarab
frail schooner
#

I think I saw someone import something from string library in the morning.. dont remember it now

hallow vapor
frail schooner
#

or ascii_letters

broken condorBOT
#

@real musk :white_check_mark: Your 3.11 eval job has completed with return code 0.

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
frail schooner
#

wait why didnt you just import that instead of those two separate ones xD

frail schooner
#

meh, it would have taken less characters

#

but okay

full scarab
real musk
#

you also could use ord

full scarab
#

well i don't think start= is required

real musk
#

wait

full scarab
#

since start is the 2nd arg

dark fjord
#

With all the new knowledge this is my final result for part 1

print(sum(((l:=len(r)//2,ord(*(set(r[:l])&set(r[l:])))-96)[1]%58for r in data)))
real musk
#

chr*

full scarab
real musk
#

talking about generating the alphabet

full scarab
hallow vapor
real musk
full scarab
frail schooner
#

!e print(sum(((l:=len(r)//2,ord(*(set(r[:l])&set(r[l:])))-96)[1]%58for r in [[1,2,3,4,5,6,7,8]])))

broken condorBOT
#

@frail schooner :x: Your 3.11 eval job has completed with return code 1.

001 | <string>:1: SyntaxWarning: invalid decimal literal
002 | Traceback (most recent call last):
003 |   File "<string>", line 1, in <module>
004 |   File "<string>", line 1, in <genexpr>
005 | TypeError: ord() takes exactly one argument (0 given)
dark fjord
#
print(sum(((l:=len(r)//2,ord(*(set(r[:l])&set(r[l:])))-96)[1]%58for r in [[1,2,3,4,5,6,7,8]])))
frail schooner
#

!e print(sum(((l:=len(r)//2,ord(*(set(r[:l])&set(r[l:])))-96)[1]%58for r in [[1,2,3,4,5,6,7,8]])))

broken condorBOT
#

@frail schooner :x: Your 3.11 eval job has completed with return code 1.

001 | <string>:1: SyntaxWarning: invalid decimal literal
002 | Traceback (most recent call last):
003 |   File "<string>", line 1, in <module>
004 |   File "<string>", line 1, in <genexpr>
005 | TypeError: ord() takes exactly one argument (0 given)
frail schooner
#

I am just copying your code

dark fjord
#

That isn't a valid input tough

full scarab
#

i was trying to simplify ```py
set(buffer[0]) & set(buffer[1]) & set(buffer[2])

e.g can't do the first two then do the last one (or am i wrong?)
frail schooner
#

oh right

#

!e print(sum(((l:=len(r)//2,ord(*(set(r[:l])&set(r[l:])))-96)[1]%58for r in [['xAbchasjhHgsdG']])))

broken condorBOT
#

@frail schooner :x: Your 3.11 eval job has completed with return code 1.

001 | <string>:1: SyntaxWarning: invalid decimal literal
002 | Traceback (most recent call last):
003 |   File "<string>", line 1, in <module>
004 |   File "<string>", line 1, in <genexpr>
005 | TypeError: ord() takes exactly one argument (0 given)
frail schooner
#

!e print(sum(((l:=len(r)//2,ord(*(set(r[:l])&set(r[l:])))-96)[1]%58for r in ['xAbYHu'])))

broken condorBOT
#

@frail schooner :x: Your 3.10 eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 1, in <module>
003 |   File "<string>", line 1, in <genexpr>
004 | TypeError: ord() takes exactly one argument (2 given)
sand jungle
frail schooner
#

!e print(sum(((l:=len(r)//2,ord(*(set(r[:l])&set(r[l:])))-96)[1]%58for r in ['xAbYHu'])))

broken condorBOT
#

@frail schooner :x: Your 3.11 eval job has completed with return code 1.

001 | <string>:1: SyntaxWarning: invalid decimal literal
002 | Traceback (most recent call last):
003 |   File "<string>", line 1, in <module>
004 |   File "<string>", line 1, in <genexpr>
005 | TypeError: ord() takes exactly one argument (0 given)
frail schooner
#

!e print(sum(((l:=len(r)//2,ord(*(set(r[:l])&set(r[l:])))-96)[1]%58for r in ['xAbYAu'])))

broken condorBOT
#

@frail schooner :white_check_mark: Your 3.11 eval job has completed with return code 0.

001 | <string>:1: SyntaxWarning: invalid decimal literal
002 | 27
frail schooner
#

okay finally

oak estuary
#

okay I found the actual solution to what I had 😭

frail schooner
oak estuary
#

basically for every new line, I had to stop comparing to the last line

#

which fixed it

#

!!!!

frail schooner
#

xD

dark fjord
#

part 2 :3 ```py
print(sum([(ord(*(set(x[0])&set(x[1])&set(x[2])))-96)%58 for x in [data[i:i+3] for i in range(0, len(data), 3)]]))

sand jungle
dark fjord
cursive sail
#

you can shave off some whitespace there

print(sum([(ord(*(set(x[0])&set(x[1])&set(x[2])))-96)%58for x in[data[i:i+3]for i in range(0,len(data),3)]]))
woeful phoenix
#

what do the different codes mean in this? (lf, cr...)

cursive sail
#

that's the newline sequence

#

windows uses carriage return (cr) line feed (lf), unix uses line feed, old macos uses carriage return

dark fjord
cursive sail
#

the space before the for is unneeded

dark fjord
#

lmao yeah but my ide is on drugs if I do that.

#

And... I like it like this. I'm gonna stop now... ||maybe if I kept going it will be 10 characters long.||

wanton arrow
wanton arrow
#

what does your data = line look like? You could move the ord part there.

azure cargo
#

sets are cool py def day3(inp: str) -> tuple[int, int]: sco = 0 slc = inp.strip().split("\n") for i in slc: num = int(len(i) / 2) a, b = i[:num], i[num:] ins = list(set(a) & set(b))[0] sco += list(" abcdefghijklmnopqrstuvwxyz" + "abcdefghijklmnopqrstuvwxyz".upper()).index(ins) gsco = 0 for i, j, k in zip(slc[::3], slc[1::3], slc[2::3]): gsco += list(" abcdefghijklmnopqrstuvwxyz" + "abcdefghijklmnopqrstuvwxyz".upper()).index(list(set(i) & set(j) & set(k))[0]) return (sco, gsco)

wanton arrow
azure cargo
#

nonono BAD

#

use f.read().strip().splitlines()

#

trailing newline

dark fjord
#

!e ```py
data = """dWlhclDHdFvDCCDfFq
mGdZBZBwRGjZMFgvTvgtvv
jwwJrzdzGdSbGGnNlzWczHzPHPhn
cczcbMBszhzzDBTBPPPGjtvtlt
LqJLfpwdLnvQLRGQjGtj
gSgnSJJCGSGpGSrwgfhchmmmHzcrHDmbrmMm""".split("\n")

print(sum(((l:=len(r)//2,ord(*(set(r[:l])&set(r[l:])))-96)[1]%58 for r in data)))

broken condorBOT
#

@dark fjord :white_check_mark: Your 3.11 eval job has completed with return code 0.

192
dark fjord
azure cargo
#

but for the actual data...

dark fjord
#

There aren't any trailing whitespaces so it doesn't matter.

azure cargo
#

there are

#

trailing newlines

fleet ivy
#
#part 1
def dupe(sttr):
    '''finds dupe characters in the string but needs to make sure
    :param sttr: string
    :return string: character that is in twice, but only once in each half of the string
    '''
    for char in sttr:
        if sttr[len(sttr) // 2:].count(char) >= 1 and sttr[:len(sttr) // 2].count(char) >= 1:
            return char
def summer(lll):
    '''sums up the priority score for each duplicate character
    :param lll: list of string
    :return int: sum of priority scores
    '''
    import string as str
    PRIORITIES = dict(zip(str.ascii_lowercase, range(1,28)))
    UPPERCASE = dict(zip(str.ascii_uppercase, range(27,53)))
    PRIORITIES.update(UPPERCASE)

    sum = 0
    for line in lll:
        sum += PRIORITIES[dupe(line)]
    return sum

with open('advent3.txt', 'r') as file:
    text = file.read().splitlines()
print(summer(text))

#part2
def dupe2(sttr1, sttr2, sttr3):
    ''' finds the character in three given strings
    :param sttr1: string
    :param sttr2: string
    :param sttr3: string
    :return string: character that is in twice, but only once in each half of the string
    '''
    for char in sttr1:
        if char in sttr2 and char in sttr3:
            return char

def summer2(lll):
    '''sums up the priority score for each duplicate character in the three string group
    :param lll: list of list of string
    :return int: sum of priority scores
    '''
    import string as str
    PRIORITIES = dict(zip(str.ascii_lowercase, range(1,28)))
    UPPERCASE = dict(zip(str.ascii_uppercase, range(27,53)))
    PRIORITIES.update(UPPERCASE)

    sum = 0
    for list in lll:
        sum += PRIORITIES[dupe2(list[0], list[1], list[2])]
    return sum

with open('advent3.txt', 'r') as file:
    text = file.read().splitlines()
lolos = [[text[index], text[index + 1], text[index + 2]] for index in range(0, len(text), 3)]
print(summer2(lolos))

I didn't even know about sets. 🤡 🤡 🤡 🤡

dark fjord
#

Not in my input.

dark fjord
fleet ivy
dark fjord
fleet ivy
#

bloody hell

dark fjord
#

!e ```py
print({1, 2, 3} & {3, 4, 5})

broken condorBOT
#

@dark fjord :white_check_mark: Your 3.11 eval job has completed with return code 0.

{3}
fleet ivy
#

Thank you

cursive sail
#

set intersection is great today

#

i'm very proud of how concise my solution was because of it

dark fjord
#

What did you come up with?

cursive sail
#
# part 1
s = 0
for r in data.splitlines():
    a, b = r[:int(len(r)/2)], r[int(len(r)/2):]
    c = list(set(a) & set(b))[0]
    s += string.ascii_letters.index(c) + 1
print(s)

# part 2
s = 0
for g in chunked(data.splitlines(), 3):
    c = list(set(g[0]) & set(g[1]) & set(g[2]))[0]
    s += string.ascii_letters.index(c) + 1
print(s)
#

that was not particularly clean though

#

i was trying to get a solution as fast as possible

#

the int(len(r)/2) should really have been floor div

proper barn
#

What's chunked?

cursive sail
#

!d more_itertools.chunked

broken condorBOT
#

more_itertools.chunked(iterable, n, strict=False)```
Break *iterable* into lists of length *n*:

```py
>>> list(chunked([1, 2, 3, 4, 5, 6], 3))
[[1, 2, 3], [4, 5, 6]]
```  By the default, the last yielded list will have fewer than *n* elements if the length of *iterable* is not divisible by *n*:

```py
>>> list(chunked([1, 2, 3, 4, 5, 6, 7, 8], 3))
[[1, 2, 3], [4, 5, 6], [7, 8]]
```  To use a fill-in value instead, see the [`grouper()`](https://more-itertools.readthedocs.io/en/stable/api.html#more_itertools.grouper "more_itertools.grouper") recipe...
cursive sail
#

it's coming as itertools.batched in 3.12

earnest sail
stray spear
cursive sail
#

i dunno

#

that's the name of it they use in the recipe in 3.11

full bane
#

I thought they use grouper

cursive sail
#

so maybe they just mostly copied that

#

oh they have both

def batched(iterable, n):
    "Batch data into lists of length n. The last batch may be shorter."
    # batched('ABCDEFG', 3) --> ABC DEF G
    if n < 1:
        raise ValueError('n must be at least one')
    it = iter(iterable)
    while (batch := list(islice(it, n))):
        yield batch
```is in there
stray spear
#

"chunks" or "chunked" is the kind of term I see a lot

#

batched...not so much

cursive sail
#

same, i like chunked

#

notably they don't have the strict from more_itertools

stray spear
#

I also have issues with pairwise

solid estuary
#

Rust Structs for the win

stray spear
#

because from math that feels like it should be about all pairs

#

not adjacent pairs

#

rust structs aren't that special

#

rust's enums are fun though

solid estuary
#

just go line by line with a counter, adding each line to a list, when the counter reaches 3 go to the next list index

stray spear
solid estuary
#

neato

hallow vapor
stray spear
cursive sail
#

eh who doesn't use nightly anyway /hj

#

if you're writing a binary, nightly is fine

#

it's not like it breaks all that often

stray spear
#

I usually do

#

this time I ended up using tuples from itertools

#

I'm assuming I could drop the 53 from the type side

#

or maybe something better still

#

oh _ for array lengths is not in stable

#

sad

#

ok, I'm dumb, I can do

let mut counts = [0u8; 53];
solid estuary
stray spear
#

wow that is so long

#

||pls don't make the obvious joke||

mystic kindle
#

day three 🎉

#

here was my solution ```py
priorities = dict(zip(string.ascii_letters, range(1, 53)))

def part_1(data: list[str]) -> int:
halves = [
next(iter(set(i[: int(len(i) / 2)]).intersection(set(i[int(len(i) / 2) :]))))
for i in data
]
priorities_sum = sum(priorities[s] for s in halves)

return priorities_sum

def part_2(data: list[str]) -> int:
chunks = chunked(data, 3)
badges = [
next(iter(set(a).intersection(set(b)).intersection(set(c))))
for a, b, c in chunks
]
priorities_sum = sum(priorities[s] for s in badges)

return priorities_sum
#

sets are nice

#

oh, you can do intersection with &, can't you

cursive sail
#

mhm

mystic kindle
#

ah, my solution would've been more concise then

#

yeah that's better ```py
priorities = dict(zip(string.ascii_letters, range(1, 53)))

def part_1(data: list[str]) -> int:
halves = [
next(iter(set(i[: int(len(i) / 2)]) & set(i[int(len(i) / 2) :]))) for i in data
]
priorities_sum = sum(priorities[s] for s in halves)

return priorities_sum

def part_2(data: list[str]) -> int:
chunks = chunked(data, 3)
badges = [next(iter(set(a) & set(b) & set(c))) for a, b, c in chunks]
priorities_sum = sum(priorities[s] for s in badges)

return priorities_sum
solid estuary
eternal cipher
#

This was mine

#

They're one liners it's just formatted

fallen sinew
full scarab
#
with open("the.txt","r") as f:
    inpt = f.read().split("\n")
    letters = "abcdefghijklmnopqrstuvwxyz"
    letters += letters.upper()
    x = []
    total = 0
    dic = {}
    for i in range(1,53):
        x.append(i)
    the_list = list(zip(letters,x))
    for i in the_list:
         dic[i[0]] = i[1]
    print(dic)
    print(dic)
    for i in inpt:
        number_of_elements = len(i)
        half_indx = (number_of_elements/2) -1
        first_half = i[0:int(half_indx)]
        second_half = i[int(half_indx):]
        common_element = set(first_half).intersection(second_half)
        for n in common_element:
            total += dic[n]
    print(total)```
#

It says too low

#

Why?

eternal cipher
#

You're taking away 1 when you divide, why?

stray spear
mystic kindle
#

time to do it in rust

solid estuary
# solid estuary

used no outside info, the only thing I looked at was the aoc prompt

stray spear
#

the time taken is...insignificant

#

I wonder what the first day with some meat to it will be pithink

cursive sail
#

what benchmarking lib is that?

#

i've only used criterion

stray spear
#

none

cursive sail
#

ah

full bane
#

i hand rolled my benchmark thing also. your percentage progress bar thing looks nice

stray spear
#

I have my own code for timing runs

#

and yeah, the display code is probably where the biggest chunk of work went 😛

full bane
#

i wrote a macro to generate a match case for all the days, which was fun

stray spear
#

I wrote a macro too, but nothing clever

full scarab
#

While the len starts at 1

full bane
# wanton arrow what does it do?

so in rust you can't dynamically use things, but i wanted to do that. i wrote a proc macro that generated a function with a match case that went

match day {
  0 => {
    // load day 0
  }
  ...
}
``` basically
full scarab
#

Oh wait

cursive sail
#

mind just does the tiniest bit more

macro_rules! days {
    ($($day:literal)*) => {
        paste! {
            $(mod [<day $day>];)*

            pub fn parts(day: u8) -> (fn(&str) -> String, fn(&str) -> String) {
                match day {
                    $($day => ([<day $day>]::part_one, [<day $day>]::part_two),)*
                    _ => panic!("invalid day"),
                }
            }
        }
    };
}

days! {
    01
}
#

the machinery is very very yucky

mystic kindle
#

man I'm just manually cargo running all my solutions

cursive sail
#

i might make it into a trait

mystic kindle
#

I was thinking of writing some small helper to automatically fetch and submit stuff, though

full bane
cursive sail
#

right now. i'll planning to change that later.

#

whenever i stop being lazy

#

will probably do some trait nonsense or something to make it cleaner

full bane
#

currently my thing just runs the functions. i want to return it also, but then i'd either have to make the functions all return strings which is sad or something else

cursive sail
#

i'll probably just make it generics

#

maybe a trait with associated types

stray spear
#

I have a run result struct that holds Box<dyn Display> for the answers

#

dumb but works

cursive sail
#

Box bad lemon_pensive /hj

#

*const () + TypeId >>>

stray spear
#

I wouldn't use it for anything performance critical

cursive sail
#

i mean Box isn't actually horrible

#

but i hate that it's magic

#

since it has the aliasing rules of &mut T or something like that

stray spear
#

it's a very good type for what's actually needed, just something that I can display

#

though I guess just wrapping stuff in format! works as well

#

and just deal with strings

#

but you can at least move that out of solutions

cursive sail
wanton arrow
#

it still feels like python should have an easier way of splitting a string in 1/2 the three methods I've seen so far all feel clunky, and 2 of them involve downloading other libraries.

mystic kindle
#

I just sliced by dividing the len in half

#

and they're all even, so it'll work fine

stray spear
#

yeah, I would say this is quite nice already

n = len(s)
s[:n//2]
s[n//2:]
full bane
#

but in rust 👀 let (l, r) = s.split_at(s.len() / 2); 👀

mystic kindle
#

more-itertools has split_at too >.>

wanton arrow
#

more itertools has divide

#

that was one of the 2

#

numpy reshape was the other.

map(set,np.fromiter(map((' '+items).index,d),int).reshape(2,-1))
mystic kindle
#

oh right

#

guess I'll refactor to use that

wanton arrow
wanton arrow
# stray spear eww
import numpy as np
from string import ascii_letters as items
data = [[*map((' '+items).index,line.strip())] for line in open(filename)]

λ=lambda d:set.intersection(*map(set,np.array(d).reshape(2,-1))).pop()
print(sum(map(λ,data)))
mystic kindle
#

oh, popping is probably a nicer way to get the first item

#

I did next(iter(...)) >.>

wanton arrow
#

yeah .pop() seems simple.

stray spear
#

!e

s = 'abcdefgh'
a, b = zip(*zip(*len(s)//2*[iter(s)]))
print(a, b)
broken condorBOT
#

@stray spear :x: Your 3.11 eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 2, in <module>
003 | ValueError: too many values to unpack (expected 2)
stray spear
#

err, maybe I should have test run this

#

oh, one zip too many

#

!e

s = 'abcdefgh'
a, b = zip(*len(s)//2*[iter(s)])
print(a, b)
broken condorBOT
#

@stray spear :white_check_mark: Your 3.11 eval job has completed with return code 0.

('a', 'b', 'c', 'd') ('e', 'f', 'g', 'h')
stray spear
#

it's terrible, but it works

dark fjord
#

!e ```py
s = 'abcdefgh'
print(*zip(4[iter(s)]))

wanton arrow
#

*zip

broken condorBOT
#

@dark fjord :white_check_mark: Your 3.10 eval job has completed with return code 0.

('a', 'b', 'c', 'd') ('e', 'f', 'g', 'h')
mystic kindle
#

oh hey, this works ```py
priorities_sum = sum(
[priorities[(set(a) & set(b)).pop()] for a, b in [divide(2, i) for i in data]]
)

wanton arrow
#
l=len(s:="abcdef")//2
print(*zip(*l*[iter(s)]))
mystic kindle
#

that's part 1 one-lined, pretty much

wanton arrow
#

except I hate seeing i be a non-int. 🙂

mystic kindle
#

lol, I read it as item

#

maybe l for line?

wanton arrow
#

d ?

#

r?

mystic kindle
#

sure

wanton arrow
#

map

mystic kindle
#

I was doing some fancy str.maketrans stuff before I realized I could just skip it and do ```py
priorities = dict(zip(string.ascii_letters, range(1, 53)))

mystic kindle
full bane
#

the chad (string.ascii_lowercase + string.ascii_uppercase).index

wise rose
#

I dunno, left, right = string[mid:], string[:mid] is pretty legible

#

ok, I got those backwards, but still

mystic kindle
#

it would've been if I calculated mid on its own line >.>

stray spear
#

I did

fn priority(n: u8) -> u8 {
  if n & 32 == 0 {
    (n & 31) + 26
  } else {
    n & 31
  }
}
#

because knowing the logic of ascii is neat

wanton arrow
#
halves = partial(divide,2)
for a,b in map(halves,data)
mystic kindle
#

a map would be more concise here, yeah

wanton arrow
#
fn priority(n: u8) -> u8 {
    n & 31 + 26 * !(n & 32)
}
cursive sail
wanton arrow
#

can you do ! for not?

full bane
#

yeah

wanton arrow
#

n & 31 + 26 * !(n & 32)

stray spear
wanton arrow
mystic kindle
#
    priorities_sum = sum(
        priorities[(set(a) & set(b) & set(c)).pop()] for a, b, c in chunked(data, 3)
    )
``` part 2 one-lined too
wanton arrow
#

I'll cut myself some slack for using a language I don't know.

#

is it rust ?

stray spear
#

it is

mystic kindle
#

more-itertools!

stray spear
#

fn is a giveaway

wanton arrow
#

chunked is good

mystic kindle
#

actually, I think salt's aoc_lube has a chunked function too, but whatever

clever dune
#

yeah, it's just chunk though

wanton arrow
clever dune
#

i don't live in the past

mystic kindle
#

lolol

stray spear
clever dune
#

actually found that often the easiest way to parse input is with a combination of extract_ints and chunk

stray spear
#

fun, func, function, defun, def

#

those I have seen around

#

not much fn

wanton arrow
clever dune
#

like, 2018 day 3 input looked like:

#1 @ 596,731: 11x27
#2 @ 20,473: 23x22
#3 @ 730,802: 23x23

and you can just

chunk(extract_ints(raw_input), 5)
mystic kindle
#

gleam uses fn, but its a lesser known thing

mystic kindle
cursive sail
#

elixir uses fn

mystic kindle
#

I thought elixir used def?

#

oh, anonymous functions?

stray spear
cursive sail
#

i think it uses fn for lambdas? i'd have to check.

clever dune
#

there's a library for reverse format strings that can help parse if you have issues

mystic kindle
#

yeah it uses fn for anonymous functions

stray spear
#

if I really need it I'll probably just bash things with regex or do something hacky

grave vapor
#

i did. intersection

mystic kindle
#

I did at first too >.>

#

I switched when I went and tried to shorten everything

grave vapor
#

i really wanna do aoc in kotlin but there aren't many good helpers 😭

clever dune
#

nim uses proc

mystic kindle
#

nim seems cool

clever dune
#

func is reserved for procs with no side effects

#

it's pretty cool

wanton arrow
#

nim does seem cool, and iirc can use python libraries and has an option to compile to python code or something like that?

#

I just don't have time at the moment for yet another language. 🙂

clever dune
#

yes, i use aoc_lube to fetch input in nim

#
import nimpy

proc fetch*(year, day: int): string =
  ## Get AoC input.
  "aoc_lube".pyImport.callMethod(string, "fetch", year, day)
#

that star after the proc name means it's public function

wanton arrow
#

it just feels like nim should be a natural progression from python, there's a lot of coupling there. I hope it does well in the future.

mystic kindle
#

I wanted to do AOC in haskell, but I forgot to properly learn it 😔

clever dune
#

my day 3 solution:

include aoc

type Sacks = seq[string] | seq[seq[char]]

let sacks = fetch(2022, 3).splitLines()

proc priority(c: char): int =
  1 + c.ord - (if c >= 'a': 'a'.ord else: 'A'.ord - 26)

proc sumPriorities(groups: seq[Sacks]): int =
  sum groups.mapIt(
    it.mapIt(it.toSet).foldl(a * b).chooseOne.priority
  )

part 1: sumPriorities sacks.mapIt(it.distribute(2))
part 2: sumPriorities sacks.chunk(3)
wanton arrow
mystic kindle
#

yeah, I'm not a fan of the star

full bane
#

feels like latex

naive oriole
#

does nim support macros

clever dune
#

yes, nim has templates and macros

mystic kindle
#

templates, like, C++ templates?

naive oriole
#

so technically you could just make a macro replacing public with *

clever dune
#

templates are like compile-time code replacements

naive oriole
#

templates would probably work better

wanton arrow
#

like pub proc fetch( seems better. but I'm complaining about a language I don't use so I have little room to stand on.

naive oriole
#

so you could put the public first

mystic kindle
#

variable names can have spaces?

stray spear
clever dune
#

did you know that snake_case and snakeCase are the same name in nim

stray spear
#

(lualatex is cheating)

clever dune
mystic kindle
#

I see

clever dune
#

actually i don't know if spaces work

mystic kindle
#

what's up with part 1, then?

cursive sail
stray spear
clever dune
#

but operators are done with:

proc `+`(a: MyClass): MyClass =
  ...
mystic kindle
#

does it ignore cases and special characters?

naive oriole
clever dune
#

no, the first letter case matters

cursive sail
full bane
mystic kindle
#

tfw arithmetic has side effects >.>

stray spear
clever dune
naive oriole
#

still less "clever" than JS (==, var, {} + {})

naive oriole
stray spear
#

JS isn't clever, it's a clusterfuck

naive oriole
#

you don't really need two variables with a nearly exact same name

stray spear
#

so I could alternate between camel_case and snakeCase between every usage? sounds like fun

mystic kindle
#

aLMOST_SCREAMING_SNAKE_CASE

clever dune
#

the reason i like nim though is the uniform function call syntax:

type Vector = tuple[x, y: int]
 
proc add(a, b: Vector): Vector =
  (a.x + b.x, a.y + b.y)
 
let
  v1 = (x: -1, y: 4)
  v2 = (x: 5, y: -2)
 
  # all the following are equivalent
  v3 = add(v1, v2)
  v4 = v1.add(v2)
  v5 = v1.add v2
full bane
#

core dev sponsored obfuscation

cursive sail
#

i can get on board with those first two, but the last scares me

lunar lance
cursive sail
#

i don't mind parenless function application, but i've never seen them optional

clever dune
#

you whitespace hater

naive oriole
clever dune
#

but it makes dot auto-complete really good

cursive sail
#

i use haskell sometimes, which does function application without parens too

#

but having both is weird to me

clever dune
#

i really hate parens, mostly because of the difficulty in typing them

#

shift + 9/0 is the most awkward combination

naive oriole
#

Shift + 9 and Shift + 0 are so far

#

Though none of !@#$%^&*() are particularly simple, yet are used very often

clever dune
#

the curly and square brackets are much better

naive oriole
#

[]{} are fine

#

also

#

-=_+ are annoying

#

particularly +_

mystic kindle
#

That's why real programmers swap the top letter row with the number row

cursive sail
#

i usually keep my right hand a little further right on my keyboard than normal

#

so it's strange to hear that these are difficult for some

mystic kindle
#

I don't have much problem typing special characters, yeah. But I guess it does vary person to person

naive oriole
#

not difficult per se but difficult compared to asdfhjlk

clever dune
#

i do shift combinations one-handed --- pinky on right shift + middle-finger on parens is so weird

cursive sail
#

i've been tempted to completely remap certain key combos on my keyboard to arbitrary symbols, but i can't figure out how to do it nicely on windows lemon_pensive

naive oriole
#

Razer supports complete keyboard remapping

stray spear
#

[](){} is good to practice of you need to type C++ lambdas

mystic kindle
#

are you on a laptop?

dark fjord
naive oriole
naive oriole
mystic kindle
#

Or do you use an external keyboard?

naive oriole
#

I use a laptop

#

that I literally never move

dark fjord
#

I got the keychron k8 pro recently.

mystic kindle
#

mechanical keyboards >>

stray spear
clever dune
stray spear
#

but very close

mystic kindle
#

I've been putting together my first custom board for the past few weeks

dark fjord
#

@clever dune Use <url> to suppress embeds.

naive oriole
stray spear
#

oh god, vtables

naive oriole
#

the macro *class looks insane for a macro

stray spear
clever dune
#

for this, they only exist at compile time

#

spits out some normal nim objects and functions at the end

#

i've seen some aoc helpers in nim that use macros that turn something like:

day 1:
    part 1:
        some_code()
    
    part 2:
        some_more_code()

into auto-submissions

stray spear
#

idk, I'm all for automating tedious things

naive oriole
#

I mean that sounds good

stray spear
#

but I've never seen a need for that

#

submitting is close enough to being a one-off thing that I don't feel the need to automate it

naive oriole
#

I've just been too lazy to automate it honestly

stray spear
#

so you save a few seconds 25 times a year

#

let me find the relevant xkcd...

wanton arrow
#

I'm not fast enough that automating the submission would help, worse it might get the wrong answer. lol

clever dune
#

it's not just saving time --- it's very easy to read

stray spear
#
#

(and don't get me wrong, I love automating stuff, I use vim and write a lot of small scripts)

#

(thinks just have to start annoy me by being tedious for me to automate them)

quiet heath
#

whilst others code golf, I've been adding type hints to my code instead XD

#

all my solutions pass mypy with strict mode

plush crater
#
uppercase = string.ascii_uppercase
lowercase = string.ascii_lowercase
letters =   dict(enumerate((lowercase + uppercase),1))

common_letters = ''
total = 0
def clean(first_half,second_half):
    global common_letters 
    for letter in first_half:
        if letter in second_half:
            common_letters += letter
            return

with open('zzzinp.text','r') as file:
    compartment = file.readlines()
    for line in compartment:
        half = len(line)// 2
        clean(line[:half],line[half:])

# 
def get_key(val,my_dict):
    for key, value in my_dict.items():
        if val == value:
            return int(key)
    return 0
print(common_letters)
for common in common_letters:
    total += get_key(common,letters)
print(total) ```
#

onto 2nd

broken condorBOT
#

When adding functions or classes to a program, it can be tempting to reference inaccessible variables by declaring them as global. Doing this can result in code that is harder to read, debug and test. Instead of using globals, pass variables or objects as parameters and receive return values.

Instead of writing

def update_score():
    global score, roll
    score = score + roll
update_score()

do this instead

def update_score(score, roll):
    return score + roll
score = update_score(score, roll)

For in-depth explanations on why global variables are bad news in a variety of situations, see this Stack Overflow answer.

wanton arrow
#

also, you can reverse the indexes of a dict by swapping the key/value.

letters = {v:k for k,v in enumerate((string.ascii_letters),1)}

oh and ascii_letters is lowercase + uppercase, so you can use that too. 🙂

plush crater
#

thanks man

#

i spent so much time on y it isen't possible to get key from value

#

😭