"Advent of Code 2018" - d3d1rty

This year's Advent of Code event has kicked off, and I will be participating for the first time. Coming off the build and launch of this textboard, I'm hoping that completing the daily challenges will be a good change of pace from Rails development.

The first challenge was fun; here are my solutions for part one and two (in Ruby):

``````# Part One
frequency = 0
f = File.open('./first_day_input.txt', 'r')

while line=f.gets
frequency += line.to_i
end

puts frequency

# Part Two
frequency = 0
observed_frequencies = []
found_duplicate = false
while !(found_duplicate)
f = File.open('./first_day_input.txt', 'r')
while line=f.gets
frequency += line.to_i
if observed_frequencies.include?(frequency)
found_duplicate = true
return frequency
end
observed_frequencies.push(frequency)
end
end

puts frequency
``````

I'm sure there are more performant solutions out there, but I'm mostly just shooting for completion of the overall event rather than seeking optimal solutions for each challenge. My rationalization for this is that a low-level of effort is easier to sustain for 25 days than a more deeply-thought out approach. I'm trying to keep it fun.

Is anyone else participating in the Advent of Code event this year? If so, post your solutions and/or thoughts on the challenges.

Anon - #6

My solution is literally the same. I am just using python.
I switched to a dict, because I thought i was doing something wrong with the array I used before.
But I just didn't read properly and forgot to repeat the offsets. Dunno How long I'll keep at it, but the first problem was neat.

``````#!/usr/bin/python3

all_f = {}
curr_f = 0
found = False

while found == False:
for line in lines:
if int(curr_f) not in all_f:
all_f[curr_f] = 1
else:
# we've already seen that. end.
found = True
break
curr_f += int(line)

print(curr_f)
``````
Anon - #8

Meh, pretty ugly solutions for today, but don't have the patience to optimize rn

Part1:

``````#!/usr/bin/python3

two = 0
three = 0

for line in lines:
tmp = {}
found_two = False
found_three = False
for c in line:
if c not in tmp:
tmp[c] = 1
else:
tmp[c] += 1

for key, value in tmp.items():
if found_two == False and value == 2:
two += 1
found_two = True
if found_three == False and value == 3:
three += 1
found_three = True

print("two: %d, three: %d" % (two, three))
print(two*three)

``````

Part2:
```python
#!/usr/bin/python3

def comparestring(str1, str2):
diff = 0
diff
index = 0
for i in range(0, len(str1)):
if str1[i] != str2[i]:
diff += 1
diff_index = i

``````    if diff > 1:
return -1

return diff_index
``````

final_str = ""

for i in range(0, len(lines)):
for j in range(1, len(lines)):
if i == j:
continue
ret = compare_string(lines[i], lines[j])
if ret != -1:
print("Result: %s" % lines[i][:ret] + lines[i][ret+1:])
exit(0)`

Anon - #9

Edit part2:

``````#!/usr/bin/python3

def compare_string(str1, str2):
diff = 0
diff_index = 0
for i in range(0, len(str1)):
if str1[i] != str2[i]:
diff += 1
diff_index = i

if diff > 1:
return -1

return diff_index

final_str = ""

for i in range(0, len(lines)):
for j in range(1, len(lines)):
if i == j:
continue
ret = compare_string(lines[i], lines[j])
if ret != -1:
print("Result: %s" % lines[i][:ret] + lines[i][ret+1:])
exit(0)

``````
Anon - #10

python : second one find my lagging a bit ;)

from itertools import cycle

def returnData(filename):

``````data = []

data.append(int(line))

return data
``````

frequency = 0

``````for variation in returnData(filename):
frequency += variation

return frequency
``````

``````frequency = 0
ledger = [0]

frequency += variation
ledger.append(frequency)

if (len(ledger) != len(set(ledger))):
return(frequency)
``````

d3d1rty - #11

Nice, Anon! I've added "Generate a Preview" functionality in the card footer for replies and posts, in case you find that useful. I was about to get started on my day 2, but the police are raiding one of my neighbors which is prime-time entertainment!

d3d1rty - #12

Here's my day 2 solution. For a second, I thought I wasn't going to get it.

Part 1:

``````#! /bin/bash ruby
f = File.open('day02/second_day_input.txt', 'r')
box_ids_for_dubs = 0
box_ids_for_trips = 0

# Part One
while line=f.gets
tally = {}
line.each_char do |c|
if tally[c]
tally[c] += 1
else
tally[c] = 1
end
end

found_dubs = false
found_trips = false
tally.each do |key, value|
found_dubs = true if value == 2
found_trips = true if value == 3
end
box_ids_for_dubs += 1 if found_dubs == true
box_ids_for_trips += 1 if found_trips == true
found_dubs = false
found_trips = false
end

checksum = box_ids_for_dubs * box_ids_for_trips
puts checksum
``````
d3d1rty - #13

Part 2:

``````# Part Two
f = File.open('day02/second_day_input.txt', 'r')
line_str_maps = []
target_boxes = []
while line=f.gets
string_arr = []
line.chomp.each_char do |c|
string_arr.push(c)
end
line_str_maps.push(string_arr)
end

line_str_maps.each_with_index do |str_arr, index|
str_arr.each_with_index do |char, str_index|
line_str_maps.each_with_index do |compare_arr, i|
num_diff = 0
diff_index = 0
next if i == index
compare_arr.each_with_index do |c, c_str_index|
num_diff += 1 unless str_arr[c_str_index] == compare_arr[c_str_index]
break if num_diff > 1
diff_index = c_str_index if str_arr[c_str_index] == compare_arr[c_str_index]
end
if num_diff == 1 && str_index == diff_index
target_boxes.push(str_arr.join.to_s)
target_boxes.push(compare_arr.join.to_s)
end
end
end
end

boxes = target_boxes.uniq

chars = boxes.first.length
diff_index = 0

chars.times do |i|
next if boxes.first[i] == boxes.last[i]
diff_index = i
end

puts boxes.first.slice(0..diff_index-1) + boxes.first.slice(diff_index+1..-1)
``````
d3d1rty - #14
almost 2 years ago

# Day 3

I'll be honest: from reading the challenge, I didn't think I was going to get this one. Turned out to be way easier than I thought, and this time I actually defined methods to simplify it a bit.

## Part One

``````##
# Initialize 2d array to represent fabric.
def draw_board(x, y)
x_arr = []
x.times do
y_arr = []
y.times do
y_arr.push('.')
end
x_arr.push(y_arr)
end
x_arr
end

##
# Draws a pattern on the fabric.
def draw_pattern(board, id, start_x, x_mod, start_y, y_mod)
y_mod.times do |i|
x_mod.times do |index|
if board[start_y+i][start_x+index] == '.'
board[start_y+i][start_x+index] = id
else
board[start_y+i][start_x+index] = '#'
end
end
end
board
end

f = File.open('third_day_input.txt', 'r')
board = draw_board(1000,1000)

while line=f.gets
args = line.scan(/\d+/)
board = draw_pattern(board, args[0], args[1].to_i, args[3].to_i, args[2].to_i, args[4].to_i)
end

overlapped_inches = 0
board.each do |row|
row.each do |inch|
overlapped_inches += 1 if inch == '#'
end
end

puts overlapped_inches
``````

## Part 2

``````##
# Checks if a pattern is overlapped with another.
def is_overlapped?(board, id, start_x, x_mod, start_y, y_mod)
found_overlap = false
y_mod.times do |i|
x_mod.times do |index|
found_overlap = true unless board[start_y+i][start_x+index] == id
end
end
found_overlap
end

f = File.open('third_day_input.txt', 'r')
no_overlaps = ''

while line=f.gets
args = line.scan(/\d+/)
no_overlaps = args[0] unless is_overlapped?(board, args[0], args[1].to_i, args[3].to_i, args[2].to_i, args[4].to_i)
end

puts no_overlaps
``````
Anon - #30
almost 2 years ago

Here is my solution for day4.
It feels like this is a super ugly solution, but it worked out. So many fucking loops. My solutions for part1 and 2 are basically the same, so here is just the one for part2:

``````#!/usr/bin/python3

from datetime import datetime
import re
import operator

events = []
# gather all events
for line in lines:
event = {}
datestr = re.match(r"[^[]*\[([^]]*)\]", line).groups()[0]
date = datetime.strptime(datestr, "%Y-%m-%d %H:%M")
action = line.split(']')[1].lstrip().rstrip()

event['time'] = date
if action == "falls asleep":
event['action'] = "sleep"
elif action == "wakes up":
event['action'] = "wake"
else:
regex = re.compile(r"#[\d]+")
matches = regex.search(line)
event['action'] = matches.group()
events.append(event)

#sort them by time
sorted_events = sorted(events, key=lambda k: k['time'])

# find out when they were asleep and count up total minutes
guards = {}
curr_guardid = ""
last_sleep = 0
for event in sorted_events:
if event['action'] == "sleep":
last_sleep = event['time'].minute
elif event['action'] == "wake":
wake_minute = event['time'].minute
guards[curr_guardid]['ranges'].append(range(last_sleep, wake_minute))
guards[curr_guardid]['minutes'] += abs(last_sleep - wake_minute)
last_sleep = 0
else:
if event['action'] not in guards:
guards[event['action']] = {}
guards[event['action']]['ranges'] = []
guards[event['action']]['minutes'] = 0
curr_guardid = event['action']

# this is for part 1 only. Find the guard with the most minutes asleep
max_guard = {}
max_value = 0
for guard in guards:
if guards[guard]['minutes'] > max_value:
max_value = guards[guard]['minutes']
max_guard = guard

# find out which is the most occuring minute
#part1 doesnt need this loop: for id, g in guards.items():

g = guards[max_guard]
id = max_guard
all_max = {}
for id, g in guards.items():
times_asleep = {}
for i in range(0, len(g['ranges'])):
for j in range(i+1, len(g['ranges'])):
a = g['ranges'][i]
b = g['ranges'][j]
if a == b:
continue
print("a: %s, b: %s" % (a, b))
xs = set(a)
intersect = xs.intersection(b)
for k in intersect:
if k not in times_asleep:
times_asleep[k] = 1
else:
times_asleep[k] += 1

max_minute = 0
max_count = 0
for key, val in times_asleep.items():
if val > max_count:
max_minute = key
max_count = val
all_max[id] = (max_minute, max_count)

# evalute part2 prefered minute
print(all_max)
max_minute = 0
max_count = 0
max_id = ""
for key, val in all_max.items():
minute, count = val
if count >= max_count:
max_count = count
max_minute = minute
max_id = key

print(max_id)
print(max_minute)
``````
d3d1rty - #32
almost 2 years ago

I think your solution looks way better than mine; my solution is a pile of hot garbage:

``````require 'time'

f = File.open('fourth_day_input.txt', 'r')

unparsed_lines = []

while line=f.gets
unparsed_lines.push(line.chomp)
end

unparsed_lines.sort!

# parse each line into hash; collect guard ids for later use
parsed_lines = []
guard_ids = []
unparsed_lines.each do |line|
guard_hash = {}
guard_hash[:datetime] = Time.parse(line.slice(0,18))
guard_hash[:action] = line.slice(19..-1)
guard_hash[:guard_id] = guard_hash[:action].scan(/\d+/).first
guard_ids.push(guard_hash[:guard_id]) unless guard_hash[:guard_id].nil?
parsed_lines.push(guard_hash)
end

# Set guard ids for each line
guard_id = parsed_lines[0][:guard_id]
parsed_lines.each do |hash|
if hash[:guard_id].nil?
hash[:guard_id] = guard_id
else
guard_id = hash[:guard_id]
end
end

# initialize array of guard sleep minutes
sleep_times = []
guard_ids.uniq.each do |id|
sleep_times.push({ guard_id: id, total_sleep_time: 0, minutes_asleep: [], minute_indices: [] })
end

# Populate sleep information by guard
parsed_lines.each_with_index do |line, index|
if line[:action] == 'falls asleep'
sleep_times.each do |hash|
if hash[:guard_id] == line[:guard_id]
snooze_duration = (parsed_lines[index+1][:datetime] - line[:datetime])/60
hash[:minutes_asleep].push(snooze_duration)
hash[:total_sleep_time] = hash[:minutes_asleep].sum
snooze_duration.to_i.times do |count|
hash[:minute_indices].push(line[:datetime].min + count)
end
break
end
end
end
end

# Determine which guard sleeps the most
sleepiest_guard = ''
biggest_sleep_time = 0
sleep_time_index = 0
sleep_times.each_with_index do |hash, index|
if hash[:total_sleep_time] > biggest_sleep_time
biggest_sleep_time = hash[:total_sleep_time]
sleepiest_guard = hash[:guard_id]
sleep_time_index = index
end
end

minutes = sleep_times[sleep_time_index][:minute_indices]

minute = minutes.max_by { |i| minutes.count(i) }
puts "The sleepiest guard is #{sleepiest_guard} and he slept the most at #{minute} minute."
puts "The solution for Part One is #{sleepiest_guard.to_i * minute}."

min_most_slept_at = 0
times_most_slept_at_min = 0
solution = { guard_id: '', min_most_slept_at: 0, times_most_slept_at_min: 0 }
sleep_times.each do |hash|
mins = hash[:minute_indices]
min_most_slept_at = mins.max_by { |i| mins.count(i) }
times_most_slept_at_min = mins.count(min_most_slept_at)
if times_most_slept_at_min > solution[:times_most_slept_at_min]
solution[:guard_id] = hash[:guard_id]
solution[:min_most_slept_at] = min_most_slept_at
solution[:times_most_slept_at_min] = times_most_slept_at_min
end
end

puts "The solution for Part Two is #{solution[:guard_id].to_i * solution[:min_most_slept_at]}."
``````
d3d1rty - #35
almost 2 years ago

# Day 3

I knocked mine out early this time:

``````def compare_char(a, b)
(a.match?(/[A-Z]/) && b.match?(/[a-z]/)) || (a.match?(/[a-z]/) && b.match?(/[A-Z]/))
end

def combust_chain(molecule_arr)
i = 0
while (true)
break if i == molecule_arr.length
if molecule_arr[i].casecmp?(molecule_arr[i+1])
if compare_char(molecule_arr[i], molecule_arr[i+1])
molecule_arr[i] = nil
molecule_arr[i+1] = nil
molecule_arr.compact!
next if i == 0
i -= 1
else
i += 1
end
else
i += 1
next
end
end
molecule_arr
end

f = File.open('./fifth_day_input.txt', 'r')

polymer_chain = ''
while line=f.gets
polymer_chain = line
end

molecule_arr = combust_chain(polymer_chain.split(//))

puts "The solution to Part One is: #{molecule_arr.length-1}"

results = []
'ABCDEFGHJKLMNOPQRSTUVWXYZ'.each_char do |char|
temp_chain = polymer_chain.split(//)
temp_chain.delete(char.upcase)
temp_chain.delete(char.downcase)
result = combust_chain(temp_chain)
results.push(result.length-1)
end

puts "The solution to Part Two is: #{results.sort.first}"
``````
Anon - #36
almost 2 years ago

Day 5 was quite easy tbqh.
My initial recursive try didn't work out, but iterative worked just fine.
Dunno why I had to substract one from the resulting string length, but whatever.

Here's my solution:

``````#!/usr/bin/python3

def parse(input):
prev_c = ""
i = 0
#for i in range(0, len(input)):
while(i < len(input)):
if prev_c != "" and (ord(prev_c)-32 == ord(input[i]) or ord(prev_c) == ord(input[i])-32):
input = input[:i-1] + input[i+1:]
i = 0
prev_c = ""
else:
prev_c = input[i]
i += 1
return input

def remove_polymer(input, c):
i = 0
while(i < len(input)):
if input[i] == c or input[i] == c.upper():
input = input[:i] + input[i+1:]
else:
i += 1 # do not increment if removed a char
return input

min_len = 2**32
for i in range(ord('a'), ord('z')+1):
print("current char: %c" % chr(i))
new_polymer = remove_polymer(lines, chr(i))
erg = parse(new_polymer)
if len(erg) < min_len:
min_len = len(erg)
print("got len of: %d" % len(erg))

print("min_len: %d" % (min_len-1))
``````

Part 1 was basically the first function and part 2 the second. Second part took super super long, but whatever. Maybe ill give the recursive one a shot again tomorrow (depending on the difficulty of the task for tomorrow lol)

Anon - #37
almost 2 years ago

```bash python3 polymer.py 2,28s user 0,00s system 99% cpu 2,282 total ```