diff --git a/README.md b/README.md index 9fcefee..550c054 100644 --- a/README.md +++ b/README.md @@ -2,18 +2,20 @@ ![AdventOfCode](https://img.shields.io/badge/Advent%20Of%20Code-2022-blue?style=flat-square) [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://img.shields.io/github/license/Vasile-hij/pyAOC-2022?style=flat-square) ![GitHub top Language](https://img.shields.io/github/languages/count/Vasile-hij/pyAOC-2022?style=flat-square) ![GitHub commit activity](https://img.shields.io/github/commit-activity/w/Vasile-Hij/pyAOC-2022) +`This is the most wonderful time of the year - Andy Williams` + Clone and cd to root project then: -$ poetry install +`$ poetry install` Run: -$`python main.py -v ` e.g: `python main.py -v 2201` '22' represent year 2022 and '01' is day 01. -For current year works with day only: `python main.py -v 01` -For testing sample input add `-s s`: `python main.py -v 01 s- s` +$`python main.py -v ` e.g: `python main.py -v 2201` '22' represent year 2022 and '01' is day 01. +If no year is mentioned, it will be taken automatically last year available: `python main.py -v 01`. +In this case '22' is the last year available for 'day01'. +Testing sample input add `-s s`: `python main.py -v 01 -s s` -`This is the most wonderful time of the year - Andy Williams` - + | Day | Name | Solution | Part 1 | Part 2 | Stars | |--------------------------------------------|-------------------------|----------------------|-----------|-----------|---------| | [01](https://adventofcode.com/2022/day/1) | Calorie Counting | [py](py/22/day01.py) | 66487 | 197301 | ** | @@ -23,7 +25,7 @@ For testing sample input add `-s s`: `python main.py -v 01 s- s` | [05](https://adventofcode.com/2022/day/5) | Supply Stacks | [py](py/22/day05.py) | JRVNHHCSJ | GNFBSBJLH | ** | | [06](https://adventofcode.com/2022/day/6) | Turning Trouble | [py](py/22/day06.py) | 1287 | 3716 | ** | | [07](https://adventofcode.com/2022/day/7) | No Space Left On Device | [py](py/22/day07.py) | 1367870 | 549173 | ** | -| [08](https://adventofcode.com/2022/day/8) | | [py](py/22/day08.py) | | | | +| [08](https://adventofcode.com/2022/day/8) | Treetop Tree House | [py](py/22/day08.py) | | | | | [09](https://adventofcode.com/2022/day/9) | | [py](py/22/day09.py) | | | | | [10](https://adventofcode.com/2022/day/10) | | [py](py/22/day10.py) | | | | | [11](https://adventofcode.com/2022/day/11) | | [py](py/22/day11.py) | | | | @@ -41,3 +43,11 @@ For testing sample input add `-s s`: `python main.py -v 01 s- s` | [23](https://adventofcode.com/2022/day/23) | | [py](py/22/day23.py) | | | | | [24](https://adventofcode.com/2022/day/24) | | [py](py/22/day24.py) | | | | | [25](https://adventofcode.com/2022/day/25) | | [py](py/22/day25.py) | | | | + +### TO DO: +- [x] poetry environment +- [x] run script from command line v0.1 +- [x] refactor day 01 - 04 to run with command line now +- [x] refactor run command line v0.2 to accept more functions +- [ ] refactor day 01-07 to run with command line v2 +- \ No newline at end of file diff --git a/common/util.py b/common/util.py index 971f07a..bc327f4 100644 --- a/common/util.py +++ b/common/util.py @@ -1,56 +1,97 @@ import re +from collections import Counter +separator = '─'*100 +lines = str.splitlines -def get_function(input_path, get_function_type, separator): - def function_name(function): - if function == 'int': - return 'get_data_num' - if function == 'str': - return 'get_data_str' - if function == 'str_sep': - return 'get_data_str_sep' - function_type = function_name(get_function_type) +def paragraph(text): + return text.split('\n\n') - function_mapping = { - 'get_data_num': get_data_num, - 'get_data_str': get_data_str, - 'get_data_str_sep': get_data_str_sep - } - try: - if separator is None: - return function_mapping[function_type](input_path) - return function_mapping[function_type](input_path, separator) - except KeyError: - print(f'This {function_type} is invalid!') +def helper_base(source: str, functions: callable = str, display: int = 10): + day_text = read_raw(source) + name, function, segmentation = functions() -def unpack_values(start_day): - separator = None - try: - function_type, separator = start_day() - except ValueError: + parser_function = get_function(function) - function_type = start_day() + if segmentation != 'lines': + custom_segmentation = get_function(segmentation) + segmentation = custom_segmentation(day_text.rstrip()) + else: + segmentation = lines(day_text.rstrip()) + print(name) + display_items('Raw input', day_text.splitlines(), display) + data = make_tuple(parser_function, segmentation) + if parser_function != str or parser_function != lines: + display_items('Parsed file', data, display) - return function_type, separator + return data -def get_data_num(input_path, separator=None): - with open(input_path, 'r') as file: - return [[int(item) for item in line.split() if item] for line in file.read().split(separator)] +def get_function(function: str): + method_name = function + possibles = globals().copy() + possibles.update(locals()) + method = possibles.get(method_name) + if not method: + raise NotImplementedError(f'Method {method_name} not implemented') + return method -def get_data_str(input_path): - with open(input_path, 'r') as file: - data = file.readlines() - return list(map(str.strip, data)) +def display_items(file_raw, items, display: int, separate=separator): + if display: + type_input = Counter(map(type, items)) -def get_data_str_sep(input_path, separator=None): - with open(input_path, 'r') as file: - if separator: - data = file.read().split(separator) - else: - data = file.read() - return [[item for item in line.split('\n') if item] for line in data if line] + def counter(types): + """count lines and verbose if plural""" + for types, name in types.items(): + return f'{name} {types.__name__}{"" if name == 1 else "s"}' + + print(f'{separate}\n{file_raw}: {counter(type_input)}:\n{separate}') + for line in items[:display]: + print(truncate(line)) + if display < len(items): + print('...') + + +def read_raw(source: str): + with open(source, 'r') as file: + data = file.read() + return data + + +def printer(part: str, result: str, func: callable = str, separate: str = separator): + _part = part + + match part: + case 'part_1': + _part = 'Part 1' + case 'part_2': + _part = 'Part 2' + + results = f'{_part}: {func(result)}' + return f'{separate}\n{results}\n{separate}' + + +def truncate(obj, width: int = 100, ellipsis: str = ' ...'): + string = str(obj) + if len(string) <= width: + return string + return string[:width - len(ellipsis)] + ellipsis + + +def make_tuple(function: callable, *sequences): + return tuple(map(function, *sequences)) + + +def make_list(function: callable, *sequences): + return list(map(function, *sequences)) + + +def find_digits(text: str): + return make_tuple(int, re.findall(r'[0-9]', text)) + + +four_directions = ((1, 0), (0, 1), (-1, 0), (0, -1)) diff --git a/common/util_old.py b/common/util_old.py new file mode 100644 index 0000000..40cb6dd --- /dev/null +++ b/common/util_old.py @@ -0,0 +1,56 @@ +import re + +def get_function(input_path, get_function_type, separator): + def function_name(function): + if function == 'int': + return 'get_data_num' + if function == 'str': + return 'get_data_str' + if function == 'str_sep': + return 'get_data_str_sep' + + function_type = function_name(get_function_type) + + function_mapping = { + 'get_data_num': get_data_num, + 'get_data_str': get_data_str, + 'get_data_str_sep': get_data_str_sep + } + + try: + if separator is None: + return function_mapping[function_type](input_path) + return function_mapping[function_type](input_path, separator) + except KeyError: + print(f'This {function_type} is invalid!') + + +def unpack_values(start_day): + separator = None + try: + function_type, separator = start_day() + except ValueError: + + function_type = start_day() + + return function_type, separator + + +def get_data_num(input_path, separator=None): + with open(input_path, 'r') as file: + return [[int(item) for item in line.split() if item] for line in file.read().split(separator)] + + +def get_data_str(input_path): + with open(input_path, 'r') as file: + data = file.readlines() + return list(map(str.strip, data)) + + +def get_data_str_sep(input_path, separator=None): + with open(input_path, 'r') as file: + if separator: + data = file.read().split(separator) + else: + data = file.read() + return [[item for item in line.split('\n') if item] for line in data if line] diff --git a/input/22/day08.txt b/input/22/day08.txt new file mode 100644 index 0000000..d9a8c3c --- /dev/null +++ b/input/22/day08.txt @@ -0,0 +1,99 @@ +222322213033345255533423306545562424165440655115256171674620442636621123532003623343351021112300040 +110200134424131544435511513034235114207220346712122743100173142606016164253614600344452542043234001 +130241122341034230060506400411050451436457131115555076655121366640166143420114243260041315245140033 +044201155341204150154421223651421072455456424262034065175730703125367662022422056423113110423033043 +341242043015141323013444355403421162464354167412604633147554242145501111651130260045523542142405124 +104105335542011255154624541673170452421201174751065233125053535203606402110631631303264231443334523 +022251232401442443240604013073567051751261046006060310057162723056356047312301014332262320405344224 +005045010303234050011604134516553223421500156708426287011206217044163376565240420066564035322425031 +433400302252163605112001002152533254526577025774185772532522645162112005222006334211222615202150023 +514421532420126245053363421750507267400406222575606338538284336516406721212651434025136363121253314 +145500111514555142462447264776571468434327564631361615475570716477174343523375640422633224154214330 +450422253465464405163267335560338812657620448402661157163042574016476542116027110002556401004144041 +315250435323412100266435752414460614818523238015312045767348145251346503446110002404643412031033110 +335554260614516260275514014501773808684115234652573523444781127146772327147027164546041361322264113 +552212024666234517403145053462886425015423537515312180012163268455035077313422213613314122403623422 +554116462330326333717726071743410713076038127356572547895446465004382875747801510560161030046236534 +105512113261674505476760210308840028176731611387575863387841328453867641286570312570624613101433450 +201620055416403673411402684861111672134437556816818962692824522386258176417471541216750515352320263 +100064152502471121126620147804267474177133917793419871348867649139837456117360472552512240365464543 +434125501030234366461354647212882961264276372277577656415297827484543874788435871670574372006541656 +354231632241763433421115602887827646148345796776349994375746935256394267608007744846602344220506426 +320055542235452511286776246551436249838211357522914296165427513242286591157867047217062671166212220 +630533311432024274286282747578525892839185272964722232382686773975896514921876068064231003115130640 +054351445323650230374860016787334957865672953893647532392634515193476444753234751431776670673443625 +122161643553043361465661234215425777375428328842756826885237348622679574815841302214422454334622455 +310361643547534388254741787957515835394388424384634948237897787328779899668951118145613227272341123 +553203043313014483116602739588328966436465926583287463393949837268357287783771610187112515346661056 +361112773030626240167311193287631239264325599932928434546936456455966294955629721437363071113555100 +223116444062065127823414995768335224963787626949338374537976548374532595386885887817322311512135354 +165533456256685465133638322212456677839479985883969576788652889447966945526287513125252251227266360 +050427105764654780569971719539982722683736488643647867988885285677254929533615456260111805471544762 +612564200420147420768231643572583337363778975687346456978779493453467879471982875321111751612056704 +154715031561015145153929571787325853755436888933888338496548994492842954225615713257348715562770051 +042706406641878154761493925944579827297695668447479695968796749364665547438536956376866503052450261 +111103621158778860687333696596964667768654674764978799646936368489433243322422814121081720104310375 +256106134082036385674358835842774753667963458466356667369999749769462758256568366264544861030650514 +412372400235780556155749924663448584664436986744984487994753564686643982758245295828805442657020150 +316402420685442228837832744963276587378457659649458546869353576749393683736838444639170007152747441 +343664452531110164851537867349623666557879764884856546986489797534353938689749649842383748067621444 +004444326256452015911854963372679986857738459895764946977798848396957278774226377383181551011246332 +324213275444575144439872496886847394968576968689979497664689986774356463883323582931740408774664723 +167274127524542565635816457474433733785665667989859545577574597555588393452438866921746374545730347 +312523103467383946589439238265777486435445747964954446957896799994745579737227145455742444466763354 +042101230038108485461717949225836749699798599445858954785786668636987937236256346361252208168136312 +447311762287744692475573737395565466544999496459956989976897778946499374824747773197595161266172226 +371671376376358926187663595697867739555794587855655786889854499686796363666939989643254552166201754 +305514713774776948141752365256767736786987588655596589796495868756859657723267975757697551713050730 +505672367783107579727693596546487757757799568755578685859899884563658799498726941257953878711714017 +457520154136801497456138426564536866785654498777579675857476597474753988679778543462582232418154231 +050570576377124118562748278969974597659546757999795788577798949457569458597349739399679324147816176 +064032506374261599382993468784374444687579995969557585785777758755334674823733669516557164016427124 +346565566106489839877287435227877647875697657779798687889989777455747976752522588271842557284604304 +320630184267887846149779595575797453867985966985895787576699496556963977669453525683498188461017663 +155470636481748966932554775295985386984477788779777769886686888674939686949557211549684318562843364 +355422032736165249425585822655654853976657576675655856568867858693534395443986997713966364825241516 +014307615355116598362643769888978393745848466775686878856446548776874844332797955528420388441472072 +434677415171655145937867232795798374659889895676897986696777754584999873398343952258322518308312370 +614462625176544968398772979677993886597595888444699849445968855456666794598363878647397472370611124 +342426038105820512291673236242588648634466744646845777477557645589764482986857645122398666420720742 +303446222610437533389493227477389695959868644577787974876888684975836425953723362621837202318302515 +101334031274541867475755424764549646588488959767847459756867963388465874367294735519312864601156672 +311162646802122687272848655359448638774475595989694889897479694563583798875942767189780830474311553 +670525052313105734222877229995545497896735689799858955459867784679684938565425586596166033035473164 +625002126405824409197545328243248943664786877896564684896757759666544465836966863943043883874535107 +304504507410725215339562444778866968394554865956559998446945777964348595952748915112623570510705144 +447671532535258771129625534992686968475466769559485845995386695599378847572918425825332176641466062 +022123400381035622672492659655854245887594385374756573547685957733982636227675215225616456802746606 +143231134353837650051751146983252488977634698367786398395985875992826958228379769214124442703715262 +135170610171160182526139534726928582959959837673658879565485535346824864319872955144130017452466064 +102646524660025304032183156274795333553888848798733487439766887562335538983732625811202053035706412 +105313211023023674376715267861525696823925879646687867997695888347896781494452164804031634615425042 +256205106513734680231582333362957987973927998375834773457684994689349817858524813244430142704015520 +021404347726028733646641268434424287525532769279452643745555528837589599615841240070086220361652546 +224024214320367157758819746327682985953929797339659337579259325447482167689237531580534124157434533 +432614136036164731080370551893833148799729789672732794952993828437433612152513202747342230044776363 +314003554513122735473322134512738781597463362529856243299295546734985494922406881657630707442021510 +514504073756450312710340856355119778239528232648473554453443349559599228483527304806846455610024545 +424156167665132531871223763346631626522767446256444526857773846279396461782420177025261412610600431 +440544203354025350033001226782826234581598745799586998494951719551921447963680834604761003456033433 +030261134056327505538138763401733512835785873969133667323138843188738957384853306401550446745105426 +524041041607103210643621736677777415881386586134322795167285489925353353273682055677320161701632002 +532513043015722226170325461521708421659348265984277116386737884679183833325305770247107056515000632 +450631113064541102213228045638208741315429696459599317816954821479256672633762880514531576001505104 +214165164302237003505054233882824157688219632493411326562973319962407073638136757124756516600661503 +304465104303261562212345808766401574871933592693641614758134144886301815682807153126027453244204015 +135203445204521251600013125103586202465438696331861292616228156657585723603452536740112103314030555 +514516400551406327564011243567833388064737417461387480870726483204868682076024701011125332602254113 +421341053633214625706123464303687686511262673301412775315212752511877023033424215721261615303053012 +022044105062611536144720566574153723272833357078078000286705430350220142407371067103103416226230555 +410213236064223263635201443404636873030520630316216081306535811175741246467466645353201136163050545 +303520211553166661506232367472736401455544832872162057805076267517121166516261355403030034621243454 +203254222143353045650002244735005340271145025041572764542706827413452562704066262265323455430133504 +441232355335366123446141420412727113134404853821274587121188823260264625415453362560311464455210441 +414115054424201303442043777071262633223473236654360080370734624214365605172654033011620153152523134 +412115334452334460565220356727405160520263276133202400177553665136056247040612461135000421154322204 +041335455114425155032554320512112112454416721273507036712353407602170012763156424133043141034050241 +030023102524414043125455041405115606664661260240725146305660271437703406461522205621551001134541002 +404443532404034526430106366644217325436253634242603222554235163606432511155652343363021250505540430 +324114252001344342204144440320420641222766650735522654115551234652234245431600152550532022520100132 \ No newline at end of file diff --git a/input/22/day08_sample.txt b/input/22/day08_sample.txt new file mode 100644 index 0000000..6557024 --- /dev/null +++ b/input/22/day08_sample.txt @@ -0,0 +1,5 @@ +30373 +25512 +65332 +33549 +35390 \ No newline at end of file diff --git a/main.py b/main.py index aba8302..874d0ee 100644 --- a/main.py +++ b/main.py @@ -1,26 +1,23 @@ import argparse -import logging from common.checker import clean_input from common.settings import files -from common.util import get_function, unpack_values +from common.util import helper_base, printer from importlib import import_module -def run(func, part, input_path, get_function_type, separator): - try: - result = get_function(input_path, get_function_type, separator) - print(f'{part}: {func(result)}') - except FileNotFoundError: - logging.error("File not found!") +def run(func, part, source, functions): + result = helper_base(source, functions) + print(printer(part, result, func)) if __name__ == '__main__': - _help = """ - 1. For year 2022 and day 01 type: -v 2201 ("-v" is value, "22" is directory , "01" is "day01") - 2. If you type only 2 digits, it will be considered that day, but no more than 25 (if that day is solved yet), - and year it will be the latest year available in 'input' directory. - 3. Sample day is taken by adding an "s" by the of digits: -v 01 -s s or -v 2201 -s s. - """ + _help = \ + """ + 1. For year 2022 and day 01 type: -v 2201 ("-v" is value, "22" is directory , "01" is "day01") + 2. If you type only 2 digits, it will be considered that day, but no more than 25 (if that day is solved yet), + and year it will be the latest year available in 'input' directory. + 3. Sample day is taken by adding an "s" by the of digits: -v 01 -s s or -v 2201 -s s. + """ parser = argparse.ArgumentParser(description="Run Advent of Code solution.") parser.add_argument('--value', '-v', type=int, help=_help) @@ -45,10 +42,9 @@ def run(func, part, input_path, get_function_type, separator): print('Please define input function and/or separator') continue - start_day = getattr(script, 'start_day') - get_function_type, separator = unpack_values(start_day) + functions_required = getattr(script, 'start_day') if not hasattr(script, each_day): continue - run(getattr(script, each_day), each_day, input_path, get_function_type, separator) + run(getattr(script, each_day), each_day, input_path, functions_required) diff --git a/main_old.py b/main_old.py new file mode 100644 index 0000000..2405fc1 --- /dev/null +++ b/main_old.py @@ -0,0 +1,54 @@ +import argparse +import logging +from common.checker import clean_input +from common.settings import files +from common.util_old import get_function, unpack_values +from importlib import import_module + + +def run(func, part, input_path, get_function_type, separator): + try: + result = get_function(input_path, get_function_type, separator) + print(f'{part}: {func(result)}') + except FileNotFoundError: + logging.error("File not found!") + + +if __name__ == '__main__': + _help = """ + 1. For year 2022 and day 01 type: -v 2201 ("-v" is value, "22" is directory , "01" is "day01") + 2. If you type only 2 digits, it will be considered that day, but no more than 25 (if that day is solved yet), + and year it will be the latest year available in 'input' directory. + 3. Sample day is taken by adding an "s" by the of digits: -v 01 -s s or -v 2201 -s s. + """ + + parser = argparse.ArgumentParser(description="Run Advent of Code solution.") + parser.add_argument('--value', '-v', type=int, help=_help) + parser.add_argument('--sample', '-s', type=str, help=_help) + args = parser.parse_args() + + year, day = clean_input(args.value) + sample = args.sample + + script_path = files['script_path'].format(year=year, day=day) + + if sample: + input_path = files['input_path'].format(year=year, day=day, sample="_sample") + else: + input_path = files['input_path'].format(year=year, day=day, sample='') + + script = import_module(script_path) + print(f'year: {year}, day: {day}') + + for each_day in ("part_1", "part_2"): + if not hasattr(script, 'start_day'): + print('Please define input function and/or separator') + continue + + start_day = getattr(script, 'start_day') + get_function_type, separator = unpack_values(start_day) + + if not hasattr(script, each_day): + continue + run(getattr(script, each_day), each_day, input_path, get_function_type, separator) + diff --git a/py/22/blank.py b/py/22/blank.py index e480310..1dd1e56 100644 --- a/py/22/blank.py +++ b/py/22/blank.py @@ -1,15 +1,17 @@ def start_day(): - type_data = '' - return type_data + return '' # e.g. find_digits -def helper(data): - return +def helper(_data): + return _data def part_1(data): - return + x = helper(data) + return x def part_2(data): - return + y = helper(data) + return y + diff --git a/py/22/day08.py b/py/22/day08.py new file mode 100644 index 0000000..588eacc --- /dev/null +++ b/py/22/day08.py @@ -0,0 +1,20 @@ +def start_day(): + name = '--- Day 8: Treetop Tree House ---' + parser_function = 'find_digits' + display_lines_or_paragraph = 'lines' + return name, parser_function, display_lines_or_paragraph + + +def helper(_data): + return _data + + +def part_1(data): + x = helper(data) + return x + + +def part_2(data): + # y = helper(data) + # return y + pass