Skip to content

Commit

Permalink
Add more 2023 solutions
Browse files Browse the repository at this point in the history
  • Loading branch information
orbit-stabilizer committed Dec 12, 2024
1 parent 44aaa9e commit f8e1177
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 124 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
# Ignore all text files
*.txt
.lsp
.clj-kondo
.cpcache
__pycache__
4 changes: 2 additions & 2 deletions 2023/6/part_one.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
(->> (slurp file-name)
(str/split-lines)))

(defn make-races [document]
(->> document
(defn make-races [lines]
(->> lines
(map #(re-seq #"\d+" %))
(map #(map parse-long %))
(apply map vector)))
Expand Down
23 changes: 23 additions & 0 deletions 2023/6/part_two.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
(require '[clojure.string :as str])

(defn read-file [file-name]
(->> (slurp file-name)
(str/split-lines)))

(defn make-race [lines]
(->> lines
(map #(re-seq #"\d+" %))
(map #(str/join "" %))
(map parse-long)))

(defn compute-ways-to-win [[t d]]
(let [x (/ (- t (Math/sqrt (- (* t t) (* 4 d)))) 2)
y (/ (+ t (Math/sqrt (- (* t t) (* 4 d)))) 2)]
(+ (- (- (Math/ceil y) 1) (+ (Math/floor x) 1)) 1)))

(defn main [file-name]
(->> (read-file file-name)
(make-race)
(compute-ways-to-win)))

(main "z_input.txt")
26 changes: 13 additions & 13 deletions 2023/7/part_one.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,19 @@ def __init__(self, hand: str, bid: str) -> None:
self.type = self.find_hand_type()
self.cards = self.get_cards()

def __lt__(self, other: Self):
if self.__class__ is other.__class__:
if self.type != other.type:
return self.type < other.type
else:
return self.cards < other.cards
return NotImplemented

def __eq__(self, other: Self):
if self.__class__ is other.__class__:
return self.type == other.type and self.cards == other.cards
return NotImplemented

def find_hand_type(self) -> HandType:
unique_cards = len(set(self.hand))
counts = Counter(self.hand)
Expand Down Expand Up @@ -88,19 +101,6 @@ def to_card(self, card: str) -> Card:

def get_cards(self) -> list[Card]:
return [self.to_card(card) for card in self.hand]

def __lt__(self, other: Self):
if self.__class__ is other.__class__:
if self.type != other.type:
return self.type < other.type
else:
return self.cards < other.cards
return NotImplemented

def __eq__(self, other: Self):
if self.__class__ is other.__class__:
return self.type == other.type and self.cards == other.cards
return NotImplemented


def main(text: str) -> int:
Expand Down
26 changes: 13 additions & 13 deletions 2023/7/part_two.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,19 @@ def __init__(self, hand: str, bid: str) -> None:
self.type = self.find_hand_type()
self.cards = self.get_cards()

def __lt__(self, other: Self):
if self.__class__ is other.__class__:
if self.type != other.type:
return self.type < other.type
else:
return self.cards < other.cards
return NotImplemented

def __eq__(self, other: Self):
if self.__class__ is other.__class__:
return self.type == other.type and self.cards == other.cards
return NotImplemented

def find_hand_type(self) -> HandType:
unique_cards = len(set(self.hand))
counts = Counter(self.hand)
Expand Down Expand Up @@ -98,19 +111,6 @@ def to_card(self, card: str) -> Card:

def get_cards(self) -> list[Card]:
return [self.to_card(card) for card in self.hand]

def __lt__(self, other: Self):
if self.__class__ is other.__class__:
if self.type != other.type:
return self.type < other.type
else:
return self.cards < other.cards
return NotImplemented

def __eq__(self, other: Self):
if self.__class__ is other.__class__:
return self.type == other.type and self.cards == other.cards
return NotImplemented


def main(text: str) -> int:
Expand Down
23 changes: 23 additions & 0 deletions 2023/8/part_one.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
(require '[clojure.string :as str])

(defn cycle-str [coll]
(lazy-cat coll (cycle-str coll)))

(defn build-directions [document]
(->> document
(first)
(cycle-str)))

(defn build-network [document]
(->> document
((comp next next))
(map #(str/split % #"="))))

(defn main [file-name]
(->> (slurp file-name)
(str/split-lines)
(build-network)))


(main "sample.txt")

32 changes: 13 additions & 19 deletions 2023/8/part_one.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ def build_directions(self, raw_directions: str) -> Iterator[int]:
"""
Builds an infinite repeating binary representation of the directions.
@Role: Parse data to build data structure.
Input -> Output
---------------
'LR' -> (0, 1, 0, 1, 0, 1, ...)
Expand All @@ -25,20 +23,21 @@ def build_directions(self, raw_directions: str) -> Iterator[int]:
Input
-----
raw_directions:
A string of arbitrary size containing only two characters: 'L' and 'R'.
Examples:
- 'RL'
- 'LRRRLL'
- 'LRLRLRLRLRRLRLRLR'
A string of arbitrary size containing only two characters: 'L' and 'R',
which give the directions one can go, left or right.
Examples:
- 'RL'
- 'LRRRLL'
- 'LRLRLRLRLRRLRLRLR'
Output
------
Iterator[int]:
An infinite iterator containing only two integers: 0 and 1.
Examples:
- (0, 1, 0, 1, 0, 1, ...)
- (1, 1, 0, 1, 1, 0, ...)
- (0, 0, 1, 0, 0, 1, ...)
A stream of 0s and 1s.
Examples:
- (0, 1, 0, 1, 0, 1, ...)
- (1, 1, 0, 1, 1, 0, ...)
- (0, 0, 1, 0, 0, 1, ...)
"""
to_bin = {'L': 0, 'R': 1}
return itertools.cycle([to_bin[c] for c in raw_directions])
Expand All @@ -49,8 +48,6 @@ def build_network(self, raw_network: list[str]) -> Network:
values are 2-tuples that contain the two nodes that are accessible
from the current node by going left or right.
@Role: Parse data to build data structure.
Input -> Output
---------------
['AAA = (BBB, CCC)', 'BBB = (CCC, AAA)', 'CCC = (ZZZ, ZZZ)']
Expand All @@ -60,13 +57,12 @@ def build_network(self, raw_network: list[str]) -> Network:
Input
-----
raw_network:
A list of strings that contain the network information
A list of strings that contain the network information.
Output
------
Network:
A dict[str, tuple[str, str]] containing the same information as raw_network,
just parsed into a dict.
A dict version of raw_network.
"""
network: Network = {}
for line in raw_network:
Expand All @@ -79,8 +75,6 @@ def find_steps_required(self) -> int:
"""
Navigates self.network using self.directions and finds number of steps
required to reach ZZZ starting from AAA.
@Role: Traverse data structure using another data structure.
"""
node, steps, destination = 'AAA', 0, 'ZZZ'
for direction in self.directions:
Expand Down
136 changes: 62 additions & 74 deletions 2023/8/part_two.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import itertools
from pathlib import Path
from typing import Iterator
from collections.abc import Iterator


type Network = dict[str, tuple[str, str]]
Expand All @@ -17,7 +17,8 @@ def build_directions(self, raw_directions: str) -> Iterator[int]:
Builds an infinite repeating binary representation of the directions.
@Role: Parse data to build data structure.
Input -> Output
Input -> Output
---------------
'LR' -> (0, 1, 0, 1, 0, 1, ...)
'RRL' -> (1, 1, 0, 1, 1, 0, ...)
Expand Down Expand Up @@ -81,85 +82,72 @@ def parallel_navigator(self) -> Iterator[list[str]]:
to navigate to. Skips yielding the starting nodes (the
ones ending with 'A').
"""
nodes = []
for key in self.network:
if key.endswith('A'):
nodes.append(key)

#nodes_to_yield = []
#for direction in self.directions:
# for node in nodes:
# nodes_to_yield.append(self.network[node][direction])
# yield nodes_to_yield
# nodes, nodes_to_yield = nodes_to_yield, []

threads = range(len(nodes))
record = {thread: {n: set() for n in range(self.cycle_len)} for thread in threads}
locations = {thread: 0 for thread in threads}
for thread in threads:
node, n = nodes[thread], 0
step = 0
try:
for direction in self.directions:
if node in record[thread][n]: raise ValueError
record[thread][n].add(node)
node, n = self.network[node][direction], (n + 1) % self.cycle_len
step += 1
except ValueError:
print(thread, node)
locations[thread] = step

max_location = max(locations.values())
thread_nodes = {thread: '' for thread in threads}
for thread in threads:
diff = max_location - locations[thread]
n = locations[thread]
for _ in range(diff):
node, n = self.network[node][direction], (n + 1)
thread_nodes[thread] = node
locations[thread] = n

print(locations[thread] % self.cycle_len)
distances = {thread: set() for thread in threads}
for thread in threads:
step = 0
node = thread_nodes[thread]
try:
for direction in self.directions:
#print(node)
step += 1
node = self.network[node][direction]
if node == thread_nodes[thread] and step % self.cycle_len == 2: raise ValueError
if node.endswith('Z'): distances[thread].add(step)
except ValueError:
print(f'step {thread}:', step)
pass

print(distances)
return thread_nodes

nodes = [key for key in self.network if key.endswith('A')]
for direction in self.directions:
nodes_to_yield = [self.network[node][direction] for node in nodes]
yield nodes_to_yield
nodes, nodes_to_yield = nodes_to_yield, []

def find_steps_required(self) -> int:
"""
Navigates self.network using self.parallel_navigator and finds number of steps
required to reach nodes ending with 'Z'.
@Role: Traverse data structure using another data structure.
Navigates self.network using self.parallel_navigator and finds number
of steps required to reach _Z starting from _A.
"""
pass
#steps = 0
#for nodes in self.parallel_navigator():
#steps += 1
#print(nodes)
#if all(node.endswith('Z') for node in nodes): break #return steps

steps = 1
for nodes in self.parallel_navigator():
if all(node.endswith('Z') for node in nodes): break
steps += 1
return steps

#threads = range(len(nodes))
#record: dict[int, dict[int, set[str]]] = {thread: {n: set() for n in range(self.cycle_len)} for thread in threads}
#locations = {thread: 0 for thread in threads}
#for thread in threads:
#node, n, step = nodes[thread], 0, 0
#try:
#for direction in self.directions:
#if node in record[thread][n]: raise ValueError
#record[thread][n].add(node)
#node, n = self.network[node][direction], (n + 1) % self.cycle_len
#step += 1
#except ValueError:
#print('hiiii')
#print(thread, node)
#locations[thread] = step
#
#max_location = max(locations.values())
#thread_nodes = {thread: '' for thread in threads}
#for thread in threads:
#diff = max_location - locations[thread]
#n = locations[thread]
#for _ in range(diff):
#node, n = self.network[node][direction], (n + 1)
#thread_nodes[thread] = node
#locations[thread] = n
#
#print(locations[thread] % self.cycle_len)
#distances = {thread: set() for thread in threads}
#for thread in threads:
#step = 0
#node = thread_nodes[thread]
#try:
#for direction in self.directions:
##print(node)
#step += 1
#node = self.network[node][direction]
#if node == thread_nodes[thread] and step % self.cycle_len == 2: raise ValueError
#if node.endswith('Z'): distances[thread].add(step)
#except ValueError:
#print(f'step {thread}:', step)
#
#print(distances)
#return thread_nodes


def main(document: str) -> int:
map = Map(document)
return map.parallel_navigator()
return map.find_steps_required()

if __name__ == '__main__':
#print(main(Path('sample.txt').read_text()))
#print(main(Path('sample_2.txt').read_text()))
#print(main(Path('sample_3.txt').read_text()))
#print(main(Path('sample_3.txt').read_text()))
print(main(Path('z_input.txt').read_text()))
5 changes: 2 additions & 3 deletions 2023/9/part_one.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ def parse(text: str) -> list[list[int]]:

def predict_line(line: list[int]) -> int:
diffs = [lead - lag for lead, lag in zip(line[1:], line)]
if sum(line) == 0: return 0
if sum(line) == 0: return 0
return line[-1] + predict_line(diffs)

if __name__ == '__main__':
print(main(Path('document.txt').read_text()))

print(main(Path('document.txt').read_text()))

0 comments on commit f8e1177

Please sign in to comment.