Advent of Code

Gute Links und Tutorials könnt ihr hier posten.
Benutzeravatar
Kebap
User
Beiträge: 687
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

https://csacademy.com/app/graph_editor/ fand ich sehr hilfreich, um die Verbindungen zwischen Höhlen an Tag 12 zu visualisieren!
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
Benutzeravatar
Kebap
User
Beiträge: 687
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

ThomasL hat geschrieben: Sonntag 13. Dezember 2020, 21:27 wenn ich sehe, wie viele Teilnehmer keine Lösung für Teil 2 haben, auch etwas Stolz auf mich.
Ich bin nicht sicher, wo ich das sehen kann, aber habe mal versuchsweise das Leaderboard untersucht (obwohl ich nie Punkte erhalten werde, weil ich viel zu spät und dazu vergleichsweise langsam bin)

Code: Alles auswählen

These are your personal leaderboard statistics. 

Rank is your position on that leaderboard: 
1 means you were the first person to get that star, 2 means the second, 100 means the 100th, etc. 

Score is the number of points you got for that rank: 
100 for 1st, 99 for 2nd, ..., 1 for 100th, and 0 otherwise.

      --------Part 1---------   --------Part 2---------
Day       Time    Rank  Score       Time    Rank  Score
  (snip)
  3       >24h  165345      0       >24h  130186      0
  2       >24h  176249      0       >24h  181738      0
  1       >24h  211476      0       >24h  189291      0
Ich hätte ja ganz spontan vermutet, dass mein Rank hier einfach der Anzahl der Personen entspricht, die das Rätsel vor mir gelöst hatten, und somit einen früheren Rank erhalten haben (die ersten 100 dann nochmal nach Geschwindigkeit sortiert, aber hier geht es mir nur um die Anzahl) und spätere werden einfach unten angehängt.

Ich kann da auch schon gut sehen, dass weniger Leute Tag 3 lösen als Tag 1. Finde ich verständlich und einleuchtend. Die Aufgaben werden nacheinander freigeschaltet und werden schwieriger. Also werden manche Personen abspringen. Also fast zwangsläufig werden die Zahlen kleiner. Sieht man schön in Part 1.

Das gleiche gilt vermutlich für Part 1 und Part 2 am gleichen Tag. Auch hier ist die zweite Aufgabe erst sichtbar, nachdem man den ersten Part abgeschlossen hat.

So. Warum ich das zeige: Mich interessiert Tag 2. Hier haben plötzlich mehr Leute Part 2 gelöst als Part 1. Wie kann das sein? Oder sind meine Annahmen falsch? :mrgreen:
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
narpfel
User
Beiträge: 644
Registriert: Freitag 20. Oktober 2017, 16:10

@Kebap: 10 Personen lösen Teil 1 und 2. Dann löst du Teil 1. => Dein Rang für Teil 1 ist 11. Dann arbeitest du an Teil 2. In der Zeit lösen 5 weitere Personen Teil 1 und Teil 2. Dann löst du Teil 2. => Dein Rang für Teil 2 ist 16.

Wie viele Leute nur Teil 1 gelöst haben, kann man in den Stats sehen.
Benutzeravatar
Kebap
User
Beiträge: 687
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

Danke für den richtigen Link, @narpfel - aber auch das passt nicht ganz zu meinen Vermutungen...

Code: Alles auswählen

Here are the current completion statistics for each day. 
Gold indicates users that have completed both parts of a puzzle, 
while silver indicates users that have completed only the first half. 
Each * or * star represents up to 5746 users.

25   10830   5376  ***
24   12565    124  ****
23   13042   2130  ****
22   15433   5930  *****
21   19574   6295  ******
20   22483    352  *****
19   16543    249  ****
18   24853    169  ******
17   32582   1433  *******
16   32565   1645  *******
15   38174   3388  ********
14   45636   6956  **********
13   51446    881  **********
12   49389   1955  **********
11   58435    309  ************
10   65151   1769  *************
 9   63962  10314  **************
 8   68367  12023  ***************
 7   87681   2318  *****************
 6   88779   6731  ******************
 5   90364   4536  *****************
 4  102431   6113  ********************
 3  131743  35789  ******************************
 2  183989   7147  ***********************************
 1  204762  25053  *****************************************
Wieso nimmt die Zahl der erfolgreichenden Lösungen nicht durchgehend mit Aufgabennummer ab?
Wie kann man Aufgabe 21 (überhaupt erstmal erhalten und) lösen, wenn man 19 nicht besteht?

edit: Hey, wirklich, ich kann mir spätere Aufgaben ansehen (und lösen) ohne alle davor zu haben! Mind = Blown :mrgreen:

Wenn ich deine Erklärung meiner letzten Vermutungen richtig verstehe, habe ich mir zwischen Teil 1 und 2 von Tag 2 augenscheinlich so viel Zeit gelassen, dass inzwischen über 5000 weitere Personen den Teil 2 (und notwendigerweise noch mehr den Teil 1) gelöst hatten? Das kann ich leider nicht mehr nachvollziehen, weil es schon so lange her ist, aber könnte durchaus eine Erklärung sein. Ich meine, ich hatte irgendwann mal mit den allerleichtesten Aufgaben angefangen und dann aber recht schnell abgebrochen. Vielleicht wirklich genau an der Stelle. Das hatte ich nicht bedacht. Danke!
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
Benutzeravatar
Kebap
User
Beiträge: 687
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

> dann aber recht schnell abgebrochen

Bald startet schon der nächste Kalender!

Wer freut sich auch wie ich auf die neuen Aufgaben?

Will vielleicht sogar wer das Leaderboard in Angriff nehmen?
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
Benutzeravatar
Dennis89
User
Beiträge: 1152
Registriert: Freitag 11. Dezember 2020, 15:13

Ich freue mich auch, mal abgesehen vom zeitlichen, bin ich aber eher froh wenn ich die ersten 5 schaffe und trotzdem noch ein paar Stunden schlaf finde :D
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 13068
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich freue mich, VIC-20 (mit optionaler Speichererweiterung) ist mehr oder weniger bereit, und Leaderboard war noch nie mein Ziel. Da muss man ja im Grunde den Zeitpunkt abpassen, an dem die Aufgaben veröffentlicht werden, und so sehr wollte ich meine Zeit dann doch nicht auf den AoC ausrichten.

Und wenn man mit so schwacher Hardware antritt, hat das ja nicht nur Auswirkungen darauf welche Aufgaben man überhaupt lösen kann, sondern auch wie lange das schreiben und ausführen einer Lösung dauert.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

Ich freue mich auch wieder. Allerdings muss ich auch sagen, dass die Freude bei mir mit den Jahren dann doch schneller abebbt, als das noch bei den ersten zwei, drei AoCs der Fall war. Irgendwann ist immer der Punkt erreicht, wo die Aufgaben so komplex werden, dass sie sich bei mir anstauen und dann die Motivation weg ist. Und anders als am Anfang sind die viele Aufgaben ja auch nicht mehr ganz neu, sondern so ähnlich schon mal vorher vorgekommen.

Das Leaderboard interessiert mich eher weniger, aber es ist auch schade, dass daran keine Änderungen vorgenommen werden. Man könnte zum Beispiel ja als Zeitzone AoE (UTC -12) nehmen oder pro Zeitzone ein Board haben.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Das Leaderboard ist prima für alle, die an dieser Form von Stress Freude haben und sich teilweise auch Nachts den Wecker stellen ;)

AoC nutze ich gerne als Fingerübung, wenn ich Zeit dafür finde. Interessant finde ich Aufgaben, die eine versteckte Komplexität haben: wo z.B. Teil 1 mit KISS (inkl. brute force) klappt, Teil 2 aber nicht mehr. Und dann gibt es Aufgaben, da bin ich algorithmisch nicht sicher. Die nutze ich dann zum Lernen oder ich lasse sie aus und mache etwas anderes.
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Ja, ich freue mich auch schon. Kann mich den Vorredner nur anschließen, ich mache die Aufgaben wie es mir zeitlich möglich ist. Interessant finde ich auch das "optimieren" des Codes, da konnte man/ich angeregt durch andere Lösungen im Netz (Twitter) aus einem 50 Zeiler einen 2-3 Zeiler machen. Und ja, da geht es dann nicht darum, das für Anfänger lesbar zu machen.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Benutzeravatar
Dennis89
User
Beiträge: 1152
Registriert: Freitag 11. Dezember 2020, 15:13

Guten Morgen,

ich hab den Tag 1 zwar gelöst, aber nicht schön. Gibt es für Part 2 etwas von 'itertools' das ich nicht gefunden habe? Ich erstelle momentan drei Listen und entferne jedes mal den Maximalwert und ziehe danach die Summe der dritten Liste von der Gesamtsumme ab.

Grüße und Danke
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 13068
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Dennis89: Ähm, das ist mir gerade zu hoch. Ich würde in Python einfach eine Liste mit einem Eintrag pro Elf erstellen und die sortieren. Dann hat man die Top n Werte entweder am Anfang oder am Ende der Liste, je nach dem ob man beim Sortieren ``reverse=True`` angibt oder nicht.

Algorithmisch wäre es natürlich effizienter das über `heapq.nlargest()` aus der Standardbibliothek zu machen, aber bei der kleinen Datenmenge (~250 Elemente) macht einfach sortieren ja nicht wirklich einen merkbaren Unterschied.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
Dennis89
User
Beiträge: 1152
Registriert: Freitag 11. Dezember 2020, 15:13

Sortieren, ja klar. Danke für den Anstoß.
Dann zeige ich hier mal meine Lösung in Python:

Code: Alles auswählen

#!/usr/bin/env python3
from pathlib import Path

CALORIES = Path("/home/dennis/Dokumente/calories.txt")


def read_input_file(file):
    calories = []
    with open(file, encoding="UTF-8") as calories_file:
        for line in calories_file:
            try:
                calories.append(int(line))
            except ValueError:
                calories.append(None)
    return calories


def search_three_maxima(calories):
    return sum(sorted(calories, reverse=True)[:3])


def select_calories_pro_elv(calories):
    calorie_pro_elv = []
    calorie_of_all_elves = []
    for calorie in calories:
        if calorie is not None:
            calorie_pro_elv.append(calorie)
        else:
            calorie_of_all_elves.append(sum(calorie_pro_elv))
            calorie_pro_elv = []
    return calorie_of_all_elves


def main():
    calories = read_input_file(CALORIES)
    total_calories = select_calories_pro_elv(calories)
    print(max(total_calories))
    print(search_three_maxima(total_calories))


if __name__ == "__main__":
    main()
Teil 1 geht bestimmt auch besser/einfacher.
Ähm, das ist mir gerade zu hoch
Davor hatte ich die Funktion so:

Code: Alles auswählen

def search_three_maxima(calories):
    max_1 = [calorie for calorie in calories if calorie != max(calories)]
    max_2 = [calorie for calorie in max_1 if calorie != max(max_1)]
    max_3 = [calorie for calorie in max_2 if calorie != max(max_2)]
    return sum(calories) - sum(max_3)
Nach dem mir außer nummerierten Listen keine sinnvollen Namen eingefallen sind, war mir klar, dass das nicht die Lösung ist, die ich haben will.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
nezzcarth
User
Beiträge: 1633
Registriert: Samstag 16. April 2011, 12:47

Dennis89 hat geschrieben: Donnerstag 1. Dezember 2022, 12:18 Dann zeige ich hier mal meine Lösung in Python:
Tag 1 geht oft auch noch ganz gut ohne Python :) :

Code: Alles auswählen

$ awk 'BEGIN{RS="\n\n"}{sum=0;for (i=1;i<=NF;i++) sum+=$i; print sum }' day01_test.txt | sort -n | tail -n 1 
24000

$ awk 'BEGIN{RS="\n\n"}{sum=0;for (i=1;i<=NF;i++) sum+=$i; print sum }' day01_text.txt | sort -n | tail -n 3 | awk '{sum+=$0}END{print sum}' 
45000
Benutzeravatar
__blackjack__
User
Beiträge: 13068
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Meine BASIC-Lösung auf dem VIC-20 summiert gleich beim einlesen und merkt sich da schon immer die Top 3 Elfen und hat damit konstanten Speicherbedarf, der locker mit den 3½ kB RAM auskommt:

Code: Alles auswählen

   10 TI$="000000":EC=0:E1=0:E2=0:E3=0:C=0
   20 OPEN 2,8,2,"INPUT01,S"
   30 PRINT"PROCESSING ELVES..."
   40 IF ST<>0 THEN CLOSE 2:GOTO 80
   50 INPUT#2,A$:N=VAL(A$):C=C+N
   60 IF N=0 THEN GOSUB 500
   70 GOTO 40
   80 GOSUB 500:PRINT
   90 PRINT E1;E1+E2+E3
  100 PRINT TI$:END
  500 EC=EC+1:PRINT EC:PRINT"{UP}";
  510 IF C>E1 THEN E3=E2:E2=E1:E1=C:GOTO 540
  520 IF C>E2 THEN E3=E2:E2=C:GOTO 540
  530 IF C>E3 THEN E3=C
  540 C=0:RETURN
Das Programm braucht 1m22s, hauptsächlich wegen des langsamen Diskettenlaufwerks:

Code: Alles auswählen

RUN
PROCESSING ELVES...
 260
 69912  208180
000122

READY.
Python-Lösung sieht bei mir so aus:

Code: Alles auswählen

#!/usr/bin/env python3
import sys

from more_itertools import split_at

TEST_LINES = """\
1000
2000
3000

4000

5000
6000

7000
8000
9000

10000
""".splitlines()


def is_blank(line):
    return line.strip() == ""


def calculate_elves_calories(lines):
    return sorted(
        (
            sum(map(int, elve_lines))
            for elve_lines in split_at(lines, is_blank)
        ),
        reverse=True,
    )


def main():
    elves_calories = calculate_elves_calories(sys.stdin)
    assert len(elves_calories) >= 3
    print("# of elves:", len(elves_calories))
    print("Top calories:", elves_calories[0])
    print("Sum of top 3 calories:", sum(elves_calories[:3]))


def test_calculate_elves_calories():
    assert calculate_elves_calories(TEST_LINES) == [
        24000,
        11000,
        10000,
        6000,
        4000,
    ]


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
Whitie
User
Beiträge: 216
Registriert: Sonntag 4. Juni 2006, 12:39
Wohnort: Schulzendorf

Ich lass es mit den sinnvollen Namen bei AoC immer etwas schleifen :D

Code: Alles auswählen

from pathlib import Path


TEST = """\
1000
2000
3000

4000

5000
6000

7000
8000
9000

10000
"""

def get_input():
    with Path('input.txt').open() as fp:
        return fp.read()


def main():
    inp = get_input()
    calories = [sum(map(int, x.split('\n'))) for x in inp.strip().split('\n\n')]
    calories.sort(reverse=True)
    print('Part 1')
    print(calories[0])
    print('Part 2')
    print(sum(calories[:3]))


if __name__ == '__main__':
    main()
Whitie
narpfel
User
Beiträge: 644
Registriert: Freitag 20. Oktober 2017, 16:10

Golf (97 Zeichen):

Code: Alles auswählen

a=sorted(sum(map(int,c.split()))for c in open("i").read().split("\n\n"));print(a[-1],sum(a[-3:]))
Gibt es Dateisysteme, die leere Dateinamen unterstützen? :twisted:
Benutzeravatar
__blackjack__
User
Beiträge: 13068
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@narpfel: Einige von den Microcomputern der 80er brauchen nicht zwingend einen Dateinamen wenn auf Kassette gespeichert wird. Auf denen läuft aber wohl kein Python.

Wenn Du bei einem Zeichen bleibst, würde ich beim ersten Tag mit "a" anfangen. Dann kannst Du jeden Tag einen weiteren Buchstaben für die Eingabedatei verwenden. 🤣
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
narpfel
User
Beiträge: 644
Registriert: Freitag 20. Oktober 2017, 16:10

@__blackjack__: Ich hatte eher an `i`, `ı̈`, `ı̈̇`, `ı̈̈`, … gedacht.
Benutzeravatar
Dennis89
User
Beiträge: 1152
Registriert: Freitag 11. Dezember 2020, 15:13

Schafft man das heute auch in 97 Zeichen oder benötigt man eher 98? :P

Bei mir wurde es pro Part eine Datei. Vielleicht könnte ma den Aufbau umgestallten um alles in ein Programm zu schreiben, aber ich poste es hier mal so, wie es während des Spiels entstanden ist.

Code: Alles auswählen

#!/usr/bin/env python3
from pathlib import Path

STRATEGY_FILE = Path(r"C:\Users\Dennis\Documents\strategy.txt")

WINNING_COMBINATIONS = [("A", "Y"), ("B", "Z"), ("C", "X")]

DRAWING_COMBINATIONS = [("A", "X"), ("B", "Y"), ("C", "Z")]

CHOICE_TO_POINTS = {
    "X": 1,
    "Y": 2,
    "Z": 3,
}


def read_file(file):
    with open(file, encoding="UTF-8") as strategy_file:
        strategy = [line.strip("\n") for line in strategy_file]
    return strategy


def calculate_total_points(strategy):
    points = []
    for game in strategy:
        elv, me = game.split(" ")
        if (elv, me) in WINNING_COMBINATIONS:
            game_situation = 6
        elif (elv, me) in DRAWING_COMBINATIONS:
            game_situation = 3
        else:
            game_situation = 0
        points.append(game_situation + CHOICE_TO_POINTS[me])
    return sum(points)


def main():
    strategy = read_file(STRATEGY_FILE)
    total_points = calculate_total_points(strategy)
    print(total_points)


if __name__ == "__main__":
    main()

Code: Alles auswählen

#!/usr/bin/env python3
from pathlib import Path

STRATEGY_FILE = Path(r"C:\Users\Dennis\Documents\strategy.txt")

WINNING_COMBINATIONS = [("A", "B"), ("B", "C"), ("C", "A")]

CHOICE_TO_POINTS = {
    "A": 1,
    "B": 2,
    "C": 3,
}


def read_file(file):
    with open(file, encoding="UTF-8") as strategy_file:
        strategy = [line.strip("\n") for line in strategy_file]
    return strategy


def calculate_total_points(strategy):
    points = []
    for game in strategy:
        elv, game_situation = game.split(" ")
        if game_situation == 'Z':
            game_points = 6
            for situation in WINNING_COMBINATIONS:
                if situation[0] == elv:
                    tool_points = CHOICE_TO_POINTS[situation[1]]
        elif game_situation == 'Y':
            game_points = 3
            tool_points = CHOICE_TO_POINTS[elv]
        else:
            game_points = 0
            for situation in WINNING_COMBINATIONS:
                if situation[1] == elv:
                    tool_points = CHOICE_TO_POINTS[situation[0]]
        points.append(game_points + tool_points)
    return sum(points)


def main():
    strategy = read_file(STRATEGY_FILE)
    total_points = calculate_total_points(strategy)
    print(total_points)


if __name__ == "__main__":
    main()
Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Antworten