1

Тема: Advent of Code

Вирішив поділитись класною ігрою. Ось посилання на сай http://adventofcode.com/
Я почав проходити сьогодні, зараз на 3тьому дні. Особисто мене пруть такі штуки. Є якийсь свій дух

http://i.imgur.com/smMb22T.png
Хто уже грав, як враження ; )  ?

Подякували: Анатолій, Master_Sergius, leofun013

2

Re: Advent of Code

Зараз майню md5 :)

3

Re: Advent of Code

Домайнив, рівень 5 :)

4

Re: Advent of Code

Славненько, та тільки в першому ж дні написано - потрібно зібрати до 25 грудня. Що буде далі? Гра закриється?

5 Востаннє редагувалося quez (22.12.2015 00:46:32)

Re: Advent of Code

koala написав:

Домайнив, рівень 5 :)

Шось довго. Я було приготувався чекати, а воно вже й знайдене.

6

Re: Advent of Code

Перші два рівні легко зробити в "MS Excel" (або "OpenOffice Calc")

7

Re: Advent of Code

Master_Sergius написав:

Славненько, та тільки в першому ж дні написано - потрібно зібрати до 25 грудня. Що буде далі? Гра закриється?

Це традиційна європейська забавка - календар адвенту. Кожного дня - одна цукерказадача.

8 Востаннє редагувалося dot (10.12.2021 09:09:35)

Re: Advent of Code

Z nazvy i za sutjoju zrozumilo, ge poxode vid Advent Calendar, ctco je takoju soboju korobkoju z 24~25 jactcykiv, kotru vidkryvajec ctcodnja z 1 hrudnja i otrymajec jakyjsj minipodarunok, perevagno tsukerku. Moʼ navitj zustrjitcaly na nepravoslavnyx ihrax, de otrymuvaly mali bonusy.

Tut, na adventofcode.com, natomistj ctcodnja znaxodec dvi vidpovidjy, aby otrymaty vidpovidno dvi zironjky. Tut nemaje obmegenj — mogna budj-jakoju movoju tcy svojym sposobom otrymuvaty vidpovidj. Jakctco otrymaly zironjky ranjice za vsjyx, to otrymujete baly i majete zmohu popasty na spysok pocany. Mogna xiba ctco zaznatcyty, ge z nastupnym dnjom vpravy stajutj skladnjicymy.

Je mistsjova docka percostjy, tam je otcky i zironjky vykonanyx vprav. Jak potrapyty: [Leaderboard] → [Private Leaderboard] → You can join a private leaderboard by entering its join code here, de vvodyte 728806-963332f3.

Vidbuvaje sja ctcoroku z 2015. Jakctco vperce potculy, to ne zasmutcujte sja, mogete vykonuvaty v budj-jakyj denj, xiba ctco ne budutj dodatkovi zhadani baly.

Tog po sutji, to zmahannja na alqoritmy. Je vidpovidna spiljnota na Redytji. Ja podumav, a tcomu ne buty ctcosj podibnoho i tut, Ukrajynsjkoju?

Подякували: koala1

9 Востаннє редагувалося dot (01.12.2021 21:57:10)

Re: Advent of Code

Jak i kazav, percyj denj zazvytcaj duge prostenjkyj.

2021#1, Py3.9
count = 0
three = list()

with open("input.txt") as file:
    arr = [int(item) for item in file]

for i in range(1, len(arr)):
    if arr[i] > arr[i - 1]:
        count += 1

print("Part One: ", count)

count = 0

for i in range(0, len(arr) - 2):
    three.append(sum(arr[i : i + 3]))

for i in range(1, len(three)):
    if three[i] > three[i - 1]:
        count += 1

print("Part Two: ", count)
Подякували: koala1

10 Востаннє редагувалося koala (01.12.2021 22:52:06)

Re: Advent of Code

aoc.py
import requests

DATA_FILE_NAME = '{}.txt'
AOC_URL = 'https://adventofcode.com/2021/day/{}/input'
SESSION = 'PASTE-IT-HERE'

def load_data(number: str, *, verbose: bool = False) -> str:

    def log(*args, **kwargs):
        if verbose:
            print(*args, **kwargs)
            
    filename = DATA_FILE_NAME.format(number)
    try:
        with open(filename) as file:
            log(f"Cached data found, reading {filename}")
            return file.read()
    except OSError:
        log(f"Cached data in {filename} not found")
    url = AOC_URL.format(number)
    cookies = {'session':SESSION}
    log(f"Sending request to {url}")
    request = requests.get(url, cookies=cookies)
    request.raise_for_status()
    log(f"Data revieved")
    with open(filename, 'w') as file:
        log(f"Caching retrieved {len(request.text)} bytes to {filename}")
        file.write(request.text)
    return request.text
2021/1.py
import aoc

import os
 
def task1(data: str) -> int:
    depths = [int(depth) for depth in data.split()]
    return sum(1 for a, b in zip(depths, depths[1:]) if a<b)

def task2(data: str) -> int:
    depths = [int(depth) for depth in data.split()]
    sliding_windows = [sum(depths[i:i+3]) for i in range(len(depths)-2)]
    return sum(1 for a, b in zip(sliding_windows, sliding_windows[1:]) if a<b)

if __name__ == '__main__':
    data = aoc.load_data(os.path.basename(__file__).removesuffix('.py'), verbose=True)
    print(task1(data))
    print(task2(data))

Понова: додав параметр verbose для load_data, так красивіше.

Зразок виводу
Cached data in 1.txt not found
Sending request to https://adventofcode.com/2021/day/1/input
Data revieved
Caching retrieved 9775 bytes to 1.txt
1390
1457
Подякували: dot, leofun012

11 Востаннє редагувалося dot (02.12.2021 08:15:21)

Re: Advent of Code

Kruto, ctce odyn Pajtonist, mo' bude z tcym porivnjuvaty i navitj povtcyty sja u svojoho.

2021#2, Py3.9.5
commands = {
    "forward": 0,
    "up": 0,
    "down": 0,
}

with open("input.txt") as file:
    for line in file:
        position, number = line.split()
        commands[position] += int(number)

print("Part One:", commands["forward"] * (commands["down"] - commands["up"]))

aim = 0
depth = 0
forward = 0

with open("input.txt") as file:
    for line in file:
        position, number = line.split()
        number = int(number)

        if position == "forward":
            forward += number
            depth += aim * number
        else:
            aim += number if position == "down" else -number


print("Part Two:", forward * depth)

Ex, ljinjky meni vvantagyty 3.10, tam je podoba do switch.

12 Востаннє редагувалося koala (02.12.2021 09:10:25)

Re: Advent of Code

2021/2.py. Через одрук довелося тести додавати
import aoc

import os
import unittest

NUMBER = os.path.basename(__file__).removesuffix('.py')

def task1(data: str) -> int:
    SHIFTS = {'forward':(1,0),'up':(0,-1),'down':(0,1)}
    x, y = 0, 0
    for command in data.splitlines():
        command, argument = command.split()
        value = int(argument)
        dx, dy = SHIFTS[command]
        x, y = x+dx*value, y+dy*value
    return x*y
        

def task2(data: str) -> int:
    SHIFTS = {'forward':(1,1,0),'up':(0,0,-1),'down':(0,0,1)}
    x, y, aim = 0, 0, 0
    for command in data.splitlines():
        command, argument = command.split()
        value = int(argument)
        dx, dy, da = SHIFTS[command]
        x, y, aim = x + dx*value, y + dy*aim*value, aim + da*value
    return x*y

class TestDay2(unittest.TestCase):
    def test_task2(self):
        data = '''forward 5
down 5
forward 8
up 3
down 8
forward 2'''
        self.assertEqual(task2(data), 900, 'Example failed')

if __name__ == '__main__':
    #unittest.main()
    data = aoc.load_data(NUMBER, verbose=True)
    print('Task1:', task1(data))
    print('Task2:', task2(data))

У вашому способі collections.defaultdict міг би зекономити пару рядків.

Якщо хтось іще зацікавиться, наведу завдання українською (без обгортки про підводний човен Санти). Кожного дня 2 завдання зі спільними даними, 2 відкривається, якщо навести правильну відповідь на 1.
День 1. 1. Є ряд чисел, треба знайти, скільки разів відбувається збільшення відносно попереднього.
2. Те саме для суми по ковзному вікну довжиною 3.
День 2. 1. Є набір команд "вперед, вгору, вниз" (для підводного човна, ага). Рух починається з (0,0). Треба знайти добуток кінцевих координат.
2. Інша інтерпретація команд: є третій параметр човна, "ціль". "Вгору" та "вниз" зменшують і збільшують ціль, "вперед X" рухає горизонтально на X і вглиб на X*ціль. Знайти добуток кінцевих координат.

Подякували: dot1

13 Востаннє редагувалося koala (03.12.2021 00:40:26)

Re: Advent of Code

На Rust перше навіть лаконічніше. І зверніть увагу на 1.2 - ми цей момент пропустили, а Rust якось ненав'язливо до нього примусив :)

2021_1.rs
fn task1(depths: &[u32]) -> usize
{
    depths.windows(2)
          .filter(|&w|w[0]<w[1])
          .count()
}

fn task2(depths: &[u32]) -> usize
{
    depths.windows(4)
         .filter(|&w|w[0]<w[3])
         .count()

}

fn main() {
    let input = aoc::get_input_from_ini_with_year("1","2021").unwrap();
    let depths:Vec<_> = input.lines()
                             .map(|line|line.parse::<u32>().unwrap())
                             .collect();
    println!("Result1: {}", task1(&depths));
    println!("Result2: {}", task2(&depths));
}
2021_2.rs
enum Command {
    Forward(i32),
    Down(i32),
    Up(i32)
}

impl Command {
    fn new(line: &str) -> Command
    {
        let mut parts = line.split_whitespace();
        let instruction  = parts.next().unwrap();
        let value = parts.next().unwrap().parse().unwrap();
        use Command::*;
        match instruction {
            "forward" => Forward(value),
            "down"    => Down(value),
            "up"      => Up(value),
            _         => panic!("{}", instruction)
        }
    }
}

fn task1(commands: &[Command]) -> i32
{
    use Command::*;
    let (x, y) = commands.iter()
                       .fold((0,0),|(x,y), command|match command {
                        Forward(dx) => (x+dx, y),
                        Down(dy)    => (x,    y+dy),
                        Up(dy)      => (x,    y-dy)
                       });
    x*y
}

fn task2(commands: &[Command]) -> i32
{
    use Command::*;
    let (x, y, _) = commands.iter()
                          .fold((0,0,0),|(x,y,aim), command|match command {
                            Forward(v) => (x+v, y+aim*v, aim),
                            Down(da)   => (x,   y,       aim+da),
                            Up(da)     => (x,   y,       aim-da)
                           });
    x*y
}

fn main() {
    let input = aoc::get_input_from_ini_with_year("2","2021").unwrap();
    let commands:Vec<_> = input.lines()
                                .map(|line|Command::new(line))
                             .  collect();
    println!("Result1: {}", task1(&commands));
    println!("Result2: {}", task2(&commands));
}
Подякували: dot, leofun012

14

Re: Advent of Code

2021/3.py
import aoc

import os
import unittest

NUMBER = os.path.basename(__file__).removesuffix('.py')

def task1(data: str) -> int:
    numbers = data.splitlines()
    counter = [sum(int(n[i]) for n in numbers) for i in range(len(numbers[0]))]
    gamma = epsilon = ''
    for i, c in enumerate(counter):
        if c>len(numbers)/2:
            gamma += '1'
            epsilon += '0'
        else:
            gamma += '0'
            epsilon += '1'
        
    return int(gamma,2)*int(epsilon,2)
        

def task2(data: str) -> int:
    numbers = data.splitlines()
    oxygen = numbers[:]
    for i in range(len(numbers[0])):
        counter = sum(int(n[i]) for n in oxygen)
        oxygen = [number for number in oxygen if (number[i]=='1')==(counter>=len(oxygen)/2)]
        if len(oxygen)==1:
            break
    co2 = numbers[:]
    for i in range(len(numbers[0])):
        counter = sum(int(n[i]) for n in co2)
        co2 = [number for number in co2 if (number[i]=='0')!=(counter<len(co2)/2)]
        if len(co2)==1:
            break

    return int(oxygen[0],2)*int(co2[0],2)
    

class TestDay3(unittest.TestCase):
    def test_task2(self):
        data = '''00100
11110
10110
10111
10101
01111
00111
11100
10000
11001
00010
01010'''
        self.assertEqual(task2(data), 230, 'Example failed')

if __name__ == '__main__':
    #unittest.main()
    data = aoc.load_data(NUMBER, verbose=True)
    print('Task1:', task1(data))
    print('Task2:', task2(data))

Щось з умовами перемудрив, але працює.

Подякували: dot1

15

Re: Advent of Code

День 3. 1. Є набір двійкових чисел однакової довжини (але можуть починатися з 0). Треба знайти добуток двох характеристик. Перша характеристика має на i-й позиції найчастішу цифру на i-й позиції у числах з набору, друга - менш часту.
2. Ті самі числа, але процедура інша. Викидаємо всі числа, у яких на першій позиції не найчастіша цифра; далі, всі, де на другій позиції не найчастіша у залишку і т.д., поки не залишиться одне число, це і буде перша характеристика. Якщо однаково - лишається 1. Друга характеристика - так само за рідшою цифрою, якщо однаково - 0. Знову ж таки добуток.

16 Востаннє редагувалося dot (03.12.2021 17:54:20)

Re: Advent of Code

2021#3 Py3.9.5
with open("input.txt") as file:
    diagnostic = [[int(i) for i in line.strip()] for line in file]

γ = list()
ε = list()

for i in zip(*diagnostic):
    most = max(i, key=i.count)
    γ.append(str(most))
    ε.append(str(abs(most - 1)))

print("Part One:", int("".join(ε), 2) * int("".join(γ), 2))


def bit_criteria(variation: str) -> int:
    variation = 1 if variation == "oxygen" else 0
    rating = diagnostic.copy()

    for l in range(len(list(zip(*diagnostic)))):
        bit = list()

        for i in rating[:]:
            bit.append(i[l])

        ones = bit.count(1)
        zeros = bit.count(0)

        if ones == zeros:
            number = 1 if variation else 0
        elif ones > zeros:
            number = 1 if variation else 0
        else:
            number = 0 if variation else 1

        for k in rating[:]:
            if k[l] != number:
                rating.remove(k)

        if len(rating) == 1:
            rating = rating[0]
            break

    return int("".join([str(i) for i in rating]), 2)


print("Part Two:", bit_criteria("oxygen") * bit_criteria("carbon dioxide"))

17 Востаннє редагувалося dot (03.12.2021 20:10:15)

Re: Advent of Code

Ne moje, ale pobatcyv take i typu zʼoqrazmyv:

2021#3,1
r = *map(str.strip,open(0)),
F = lambda f: int(''.join([f(x, key=x.count) for x in zip(*r)]), 2)
print(F(max) * F(min))

Desj v mojomu naprjamku, bo teg tcerez max i zip, ale korotce i krasyvice.

18

Re: Advent of Code

День 4. 1. Гра Бінго. Є послідовність чисел і послідовність полів 5x5. Числа називаються по одному, коли число назване, його викреслюють з усіх полів. Визначити, на якому полі першому виникне рядок чи стовпчик із 5-и викреслених чисел і обчислити добуток невикреслених чисел на останнє назване число на цьому полі.
2. Те саме, тільки останнє поле, на якому буде викреслений стовпчик чи рядок.

2021/4.py
import aoc

import os

NUMBER = os.path.basename(__file__).removesuffix('.py')

class Bingo:
    def __init__(self, data:str):
        data = data.splitlines()
        self.numbers = [int(x) for x in data[0].split(',')]
        self.boards = []
        for line in data[1:]:
            if not line.strip():
                self.boards.append([])
            else:
                self.boards[-1].append([int(x) for x in line.split()])
        self.strikedout = [[[False for _ in line] for line in board] for board in self.boards]
        self.winners = []

    def strikeout(self, n: int):
        for board_idx, board in enumerate(self.boards):
            for line_idx, line in enumerate(board):
                if n in line:
                    self.strikedout[board_idx][line_idx][line.index(n)] = True
                    self.check_winner(board_idx)

    def check_winner(self, idx: int):
        if idx in self.winners:
            return
        board = self.strikedout[idx]
        for line in board:
            if all(line):
                self.winners.append(idx)
                return
        for i in range(len(board[0])):
            if all(line[i] for line in board):
                self.winners.append(idx)
                return

    def score(self, idx: int, n: int) -> int:
        board = self.boards[idx]
        sboard = self.strikedout[idx]
        s = 0
        for line, sline in zip(board, sboard):
            for field, sfield in zip(line, sline):
                if not sfield:
                    s += field
        return s*n

    def task(self, criterion) -> int:
        for n in self.numbers:
            self.strikeout(n)
            if criterion(self):
                result = self.score(self.winners[-1], n)
                self.strikedout = [[[False for _ in line] for line in board] for board in self.boards]
                return result
        result = self.score(self.winners[-1], self.numbers[-1])
        self.strikedout = [[[False for _ in line] for line in board] for board in self.boards]
        return result

    def task1(self) -> int:
        return self.task(lambda b:b.winners)

    def task2(self) -> int:
        return self.task(lambda b:len(b.winners)==len(b.boards))


if __name__ == '__main__':
    board = Bingo(aoc.load_data(NUMBER, verbose=True))
    print('Task1:', board.task1())
    print('Task2:', board.task2())
Подякували: dot1

19

Re: Advent of Code

2021#4, Py3.9.5
from collections import defaultdict
from itertools import chain

lines = [i.strip() for i in open("input.txt")]

boards = defaultdict(list)
b = 0

for i in range(2, len(lines)):
    if not lines[i]:
        b += 1
        continue

    boards[b].append(list(map(int, lines[i].split())))

for board in boards:
    boards[board] += list(zip(*boards[board]))

numbers = list(map(int, lines[0].split(",")))


def task(boards: list) -> list:
    scores = list()
    marked = numbers[:4]
    for number in numbers[4:]:
        marked.append(number)
        for board in list(boards):
            for b in boards[board]:
                if set(b).issubset(marked):
                    scores.append(sum(set(chain(*boards[board])) - set(marked)) * marked[-1])
                    boards.pop(board)
    return scores


print("Part One:", task(boards.copy())[0])
print("Part Two:", task(boards.copy())[-2])

20

Re: Advent of Code

koala написав:

День 4. 1. Гра Бінго. Є послідовність чисел і послідовність полів 5x5. Числа називаються по одному, коли число назване, його викреслюють з усіх полів. Визначити, на якому полі першому виникне рядок чи стовпчик із 5-и викреслених чисел і обчислити добуток невикреслених чисел на останнє назване число на цьому полі.
2. Те саме, тільки останнє поле, на якому буде викреслений стовпчик чи рядок.

2021/4.py
import aoc

import os

NUMBER = os.path.basename(__file__).removesuffix('.py')

class Bingo:
    def __init__(self, data:str):
        data = data.splitlines()
        self.numbers = [int(x) for x in data[0].split(',')]
        self.boards = []
        for line in data[1:]:
            if not line.strip():
                self.boards.append([])
            else:
                self.boards[-1].append([int(x) for x in line.split()])
        self.strikedout = [[[False for _ in line] for line in board] for board in self.boards]
        self.winners = []

    def strikeout(self, n: int):
        for board_idx, board in enumerate(self.boards):
            for line_idx, line in enumerate(board):
                if n in line:
                    self.strikedout[board_idx][line_idx][line.index(n)] = True
                    self.check_winner(board_idx)

    def check_winner(self, idx: int):
        if idx in self.winners:
            return
        board = self.strikedout[idx]
        for line in board:
            if all(line):
                self.winners.append(idx)
                return
        for i in range(len(board[0])):
            if all(line[i] for line in board):
                self.winners.append(idx)
                return

    def score(self, idx: int, n: int) -> int:
        board = self.boards[idx]
        sboard = self.strikedout[idx]
        s = 0
        for line, sline in zip(board, sboard):
            for field, sfield in zip(line, sline):
                if not sfield:
                    s += field
        return s*n

    def task(self, criterion) -> int:
        for n in self.numbers:
            self.strikeout(n)
            if criterion(self):
                result = self.score(self.winners[-1], n)
                self.strikedout = [[[False for _ in line] for line in board] for board in self.boards]
                return result
        result = self.score(self.winners[-1], self.numbers[-1])
        self.strikedout = [[[False for _ in line] for line in board] for board in self.boards]
        return result

    def task1(self) -> int:
        return self.task(lambda b:b.winners)

    def task2(self) -> int:
        return self.task(lambda b:len(b.winners)==len(b.boards))


if __name__ == '__main__':
    board = Bingo(aoc.load_data(NUMBER, verbose=True))
    print('Task1:', board.task1())
    print('Task2:', board.task2())

Oho, tcerez klasy i funtsijy, potugno.