🌟 Advent of Code (AoC) 2020 🌟

PermalÀnk
Medlem ★
●

Dag 5
Jag tragglar vidare i C# .Net 5 med mina lÄnga lösningar

public static string Run1(bool test = false) { int _Day = 5; string[] inputData = InputData.GetInputArrString(_Day, test); List<UInt16> AllSeats = new List<UInt16>(); for (UInt16 row = 0; row < 128; row++) { for (UInt16 col = 0; col < 8; col++) { UInt16 _seatId = (UInt16)((row * (UInt16)8) + col); AllSeats.Add(_seatId); } } UInt16 highestSeatId = 0; for (int i = 0; i < inputData.Length; i++) { string bp = inputData[i]; bp = bp.Replace("B", "1"); bp = bp.Replace("F", "0"); bp = bp.Replace("R", "1"); bp = bp.Replace("L", "0"); UInt16 SeatId = Convert.ToUInt16(bp, 2); if (SeatId>highestSeatId) { highestSeatId = SeatId; } AllSeats.Remove(SeatId); } UInt16 foundId = 0; foreach (UInt16 item in AllSeats) { if (!AllSeats.Contains((UInt16)(item+(UInt16)1)) && !AllSeats.Contains((UInt16)(item - (UInt16)1))) { foundId = item; } } return highestSeatId.ToString() + " : " +foundId.ToString(); }

Dold text
PermalÀnk
Hedersmedlem ★
●

Dag: 5
SprÄk: C
KĂ€llkod: https://gist.github.com/pv2b/900d35020ea06a280d4e0bcd601f9b99

Skrivet av Talarion:

Nu snackar vi optimering deluxe. Men hade du inte dÄ kunnat skippa din hashset och kolla i din seatid array ifall seatid+1 finns?
Eller det blir lÄngsammare Àn .contains() i hashsetet. TÀnkte att du itererar ÀndÄ igenom seatid.

Jag Àr nog inte lika avancerad som dig, dessa saker i AoC gör jag för att lÀra mig mer sÄ det Àr bra med feedback!

Att kolla om en array innehÄller nÄgot betyder att man mÄste gÄ igenom varje objekt.

Om man sedan behöver gÄ igenom hela arrayen en gÄng per en iteration i en loop, sÄ blir det O(n^2) till slut. TÀnk dig om nÄgon skickar in dig i flygplanet med frÄgan "Àr stol 1 ledig", och du kommer tillbaka och sÀger "nej" efter att ha kollat alla stolar (sÀg att du mÄste gÄ ut genom bakdörren...), sÄ skickar nÄgon in dig igen och frÄgar "Àr stol 2 ledig" etc. Det Àr det du gör om du gör sÄ.

Men jag hittade faktiskt en ganska optimal lösning nÀr jag skrev en till lösning i C, som lagrar information om huruvida en stol Àr upptagen i en array (fast packat som sardiner i minne eftersom det blev ett bitfÀlt.)

https://gist.github.com/pv2b/900d35020ea06a280d4e0bcd601f9b99

KÀnner mig rÀtt nöjd med hur den lösningen fungerar. Den Àr O(n) bÄde i minne och berÀkningskomplexitet.

PermalÀnk
Medlem ★
●

Dag: 4
SprÄk: Kotlin
Lösning: GitHub

Jag hÄller med om att uppgiften alldeles Àr för omstÀndlig för detta ÀndamÄl. Chore-programmering gör jag helst bara pÄ mitt arbete eller pÄ mina egna projekt. Jag var ocksÄ tvungen att debugga för att upptÀcka jag hade splittat strÀngen pÄ ett fel sÀtt. Men Ä andra sidan blev det mycket Kotlinmagi.

Jag har Àven fuskat med att anvÀnda kommentarer för att skilja pÄ metoderna/klasserna. Pallar inte skapa nya filer och sÄ.

Visa signatur

| Mobo: Gigabyte X570 GAMING X | CPU: AMD Ryzen 9 3900X + Dark Rock 4 | RAM: 32GB @ 3000MHz | GPU: Gigabyte RTX 3080 OC | PSU: Seasonic GX 850W | Chassi: NZXT S340 Elite Matte Black | M.2: Samsung 970 Evo 500GB & 1000GB | HDD: 4TB | Monitors: Acer Predator X34 GS & Acer XB270HU |

PermalÀnk
Medlem ★
●
Skrivet av Yoshman:

C har inte mycket till standardbibliotek och kanske rÄkar kunna det ovanligt vÀl dÄ jag behövt implementera standardbiblioteket C99 som del av jobbet. Men oavsett sprÄk anvÀnder ju folk standardbiblioteket, vore rÀtt hopplöst att lösa nÄgot utan det. Alla de funktioner du nÀmner Àr ju del av C89, enda jag anvÀnder frÄn C99 Àr möjlighet att deklarera variabler nÀr de först anvÀnds i stÀllet för i toppen av funktionen.

MissförstÄ mig inte hÀr, det var ingen kritik. Jag pekar bara pÄ att du anvÀnder funktioner ur standardbiblioteket, till skillnad frÄn mÄnga andra lösningar dÀr folk envisas att sjÀlv skriva kod för göra saker som borde har gjorts med en funktion ur standardbiblioteket. Det Àr sÄdant man borde kunna och borde anvÀnda. Det Àr klart det blir mycket kod om man absolut skall skriva allt sjÀlv.

Sedan vet jag inte om den nya versionen Àr lÀttare att förstÄ Àn den förra. Man fÄr tÀnka pÄ vilken publik den Àr tÀnkt för. Den gamla kanske inte var optimal för nybörjare i C, men C-program ser ju ut sÄdÀr. Vektorer av funktionspekare Àr snarare regel Àn undantag. Jag sÄg det som ett mönster som var ett anvÀndbart trick om man inte absolut vill göra allt i en switch eller göra 8 explicita anrop till de olika funktionerna. NÄgonting att stoppa i den mentala verktygslÄdan för de som inte sett det förut.

Den stora fördelen med list comprehensions (och saker som map/reduce) Àr att man slipper introducera en variabel och initiera den med en tom lista och sedan appenda ett element i taget i en loop. Koden blir enklare av att anvÀnda dem och för den vane Python-programmeraren Àr det inte det minsta konstigt. Vill man sÀtta ett namn pÄ dem kan man göra det. Sedan kan list comprehensions förstÄs missbrukas, om man tycker det Àr kul

PermalÀnk
Medlem ★
●

VB.Net fÄr alldeles för lite uppmÀrksamhet nu för tiden, sÄ hÀr kommer Dag 1-5 i VB.

Dag: 1
SprÄk: VB.Net

Imports System.IO Module Program Sub Main(args As String()) Dim expenseReport As New List(Of Integer) For Each entry In File.ReadLines("input.txt") expenseReport.Add(Integer.Parse(entry)) Next Console.WriteLine("Part 1: " & CalculatePart1(expenseReport).ToString()) Console.WriteLine("Part 2: " & CalculatePart2(expenseReport).ToString()) End Sub Function CalculatePart1(expenseReport As List(Of Integer)) As Integer For Each entry In expenseReport For Each entry2 In expenseReport If entry + entry2 = 2020 Then Return entry * entry2 End If Next Next Return 0 End Function Function CalculatePart2(expenseReport As List(Of Integer)) As Integer For Each entry In expenseReport For Each entry2 In expenseReport For Each entry3 In expenseReport If entry + entry2 + entry3 = 2020 Then Return entry * entry2 * entry3 End If Next Next Next Return 0 End Function End Module

Dold text

Dag: 2
SprÄk: VB.Net

Imports System.IO Module Program Sub Main(args As String()) Dim PartOneCount As Integer Dim PartTwoCount As Integer For Each entry In File.ReadLines("input.txt") Dim parts = entry.Split({"-"c, " "c, ":"c}, StringSplitOptions.RemoveEmptyEntries) Dim min = Integer.Parse(parts(0)) Dim max = Integer.Parse(parts(1)) Dim character = parts(2) Dim password = parts(3) Dim charCount = password.Count(Function(c) c = character) If charCount >= min And charCount <= max Then PartOneCount += 1 End If If password(min - 1) = character Xor password(max - 1) = character Then PartTwoCount += 1 End If Next Console.WriteLine("Part 1: " & PartOneCount.ToString()) Console.WriteLine("Part 2: " & PartTwoCount.ToString()) End Sub End Module

Dold text

Dag: 3
SprÄk: VB.Net

Imports System.IO Module Program Sub Main(args As String()) Dim map As List(Of String) = File.ReadLines("input.txt").ToList() Dim part1 = CalculateSlope(map, 3, 1) Dim part2 = CalculateSlope(map, 1, 1) * CalculateSlope(map, 3, 1) * CalculateSlope(map, 5, 1) * CalculateSlope(map, 7, 1) * CalculateSlope(map, 1, 2) Console.WriteLine("Part 1: " & part1.ToString()) Console.WriteLine("Part 2: " & part2.ToString()) End Sub Function CalculateSlope(map As List(Of String), stepRight As Integer, stepDown As Integer) As Long Dim treeCount As Long = 0 Dim x As Integer = 0 Dim y As Integer = 0 While y < map.Count If map(y)(x) = "#"c Then treeCount += 1 End If x = (x + stepRight) Mod map(0).Length y += stepDown End While Return treeCount End Function End Module

Dold text

Dag: 4
SprÄk: VB.Net

Imports System.IO Imports System.Text.RegularExpressions Module Program Sub Main(args As String()) Dim validCount1 As Integer = 0 Dim validCount2 As Integer = 0 Using reader As New StreamReader("input.txt") While Not reader.EndOfStream Dim passPortData As String = "" Dim line = reader.ReadLine() While Not String.IsNullOrWhiteSpace(line) passPortData += line & Environment.NewLine line = reader.ReadLine() End While If Not String.IsNullOrWhiteSpace(passPortData) Then Dim passPort As New Dictionary(Of String, String) Dim fields = passPortData.Split(New String() {" ", Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries) For Each field In fields Dim key = field.Split(":"c).First Dim value = field.Split(":"c).Last passPort.Add(key, value) Next If IsPassPortValidPartOne(passPort) Then validCount1 += 1 End If If IsPassPortValidPartTwo(passPort) Then validCount2 += 1 End If End If End While End Using Console.WriteLine("Part 1: " & validCount1.ToString()) Console.WriteLine("Part 2: " & validCount2.ToString()) End Sub Function IsPassPortValidPartOne(passPort As Dictionary(Of String, String)) As Boolean If Not (passPort.ContainsKey("byr") AndAlso Not String.IsNullOrWhiteSpace(passPort("byr"))) Then Return False If Not (passPort.ContainsKey("iyr") AndAlso Not String.IsNullOrWhiteSpace(passPort("iyr"))) Then Return False If Not (passPort.ContainsKey("eyr") AndAlso Not String.IsNullOrWhiteSpace(passPort("eyr"))) Then Return False If Not (passPort.ContainsKey("hgt") AndAlso Not String.IsNullOrWhiteSpace(passPort("hgt"))) Then Return False If Not (passPort.ContainsKey("hcl") AndAlso Not String.IsNullOrWhiteSpace(passPort("hcl"))) Then Return False If Not (passPort.ContainsKey("ecl") AndAlso Not String.IsNullOrWhiteSpace(passPort("ecl"))) Then Return False If Not (passPort.ContainsKey("pid") AndAlso Not String.IsNullOrWhiteSpace(passPort("pid"))) Then Return False Return True End Function Function IsPassPortValidPartTwo(passPort As Dictionary(Of String, String)) As Boolean If Not IsPassPortValidPartOne(passPort) Then Return False If Not (Integer.Parse(passPort("byr")) >= 1920 And Integer.Parse(passPort("byr")) <= 2002) Then Return False If Not (Integer.Parse(passPort("iyr")) >= 2010 And Integer.Parse(passPort("iyr")) <= 2020) Then Return False If Not (Integer.Parse(passPort("eyr")) >= 2020 And Integer.Parse(passPort("eyr")) <= 2030) Then Return False Dim format = Strings.Right(passPort("hgt"), 2) If Not (format = "in" Or format = "cm") Then Return False Dim height = Integer.Parse(Strings.Left(passPort("hgt"), passPort("hgt").Length - 2)) If Not ((format = "in" And height >= 59 And height <= 76) Or (format = "cm" And height >= 150 And height <= 193)) Then Return False If Not Regex.IsMatch(passPort("hcl"), "#[0-9a-f]{6}") Then Return False If Not Regex.IsMatch(passPort("ecl"), "amb|blu|brn|gry|grn|hzl|oth") Then Return False If Not (IsNumeric(passPort("pid")) And passPort("pid").Length = 9) Then Return False Return True End Function End Module

Dold text

Dag: 5
SprÄk: VB.Net

Imports System.IO Module Program Sub Main(args As String()) Dim seats As New List(Of Integer) For Each boardingPass In File.ReadLines("input.txt") seats.Add(CalculateSeatId(boardingPass)) Next seats.Sort() Console.WriteLine("Part 1: " & seats.Last.ToString()) Console.WriteLine("Part 2: " & FindMissingSeat(seats).ToString()) End Sub Function CalculateSeatId(boardingPass As String) Dim front As Integer = 0 Dim back As Integer = 127 Dim left As Integer = 0 Dim right As Integer = 7 For i = 0 To 9 If boardingPass(i) = "F"c Then back = Math.Floor((back + front) / 2) If boardingPass(i) = "B"c Then front = Math.Ceiling((back + front) / 2) If boardingPass(i) = "L"c Then right = Math.Floor((left + right) / 2) If boardingPass(i) = "R"c Then left = Math.Ceiling((left + right) / 2) Next Return front * 8 + left End Function Function FindMissingSeat(seats As List(Of Integer)) As Integer Dim seatToCheck = seats.First For i = 0 To seats.Count If seatToCheck <> seats(i) Then Return seatToCheck seatToCheck += 1 Next Return 0 End Function End Module

Dold text
PermalÀnk
Medlem ★
●

Dagens lösning exklusive FileIO tog nog 1ms oavsett sprÄk, lösning, processor men det vore kul att se exekveringstid exklusive FileIO pÄ lösningarna.

PermalÀnk
Medlem
●

Dag: 5
SprÄk: Rust

use std::io; pub fn run<R>(mut input: R) where R: io::BufRead, { let mut bps = vec![]; let mut buf = String::new(); while input.read_line(&mut buf).unwrap() != 0 { let data = buf.trim(); bps.push(process(&data[..7], 128) * 8 + process(&data[7..], 8)); buf.clear(); } bps.sort_unstable(); println!("Svar del 1: {}", bps.last().unwrap()); for (&a, &b) in bps.iter().zip(bps.iter().skip(1)) { if a + 1 != b { println!("Svar del 2: {}", a + 1); } } } fn process(data: &str, mut upper: u32) -> u32 { let mut lower = 0; for c in data.chars() { let step = (upper - lower) / 2; match c { 'F' | 'L' => upper -= step, _ => lower += step, } } lower }

Dold text
Visa signatur

AMD Ryzen 3700X, Gigabyte Elite X570, 32GB Ballistix Sport, NH-D15S, SAPPHIRE NITRO+ RX 7900 XTX, Corsair AX760, LG OLED C2 42"

PermalÀnk
Datavetare ★
●

Dag: 5
SprÄk: C++

#include <algorithm> #include <cstdio> #include <fstream> #include <string> #include <vector> unsigned seat_id(const std::string &desc) { unsigned id = 0; for (auto c: desc) { id = (id << 1) + (c == 'B' || c == 'R'); } return id; } unsigned my_seat_id(const std::vector<unsigned> &boarding_passes) { for (auto i = 0; i < boarding_passes.size() - 1; i++) { if (boarding_passes[i] + 2 == boarding_passes[i+1]) { return boarding_passes[i] + 1; } } return ~0; } std::vector<unsigned> boarding_passes_get() { std::string line; std::ifstream fin("input.txt"); std::vector<unsigned> boarding_passes; while (std::getline(fin, line)) { boarding_passes.push_back(seat_id(line)); } std::sort(boarding_passes.begin(), boarding_passes.end()); return boarding_passes; } int main() { auto boarding_passes = boarding_passes_get(); std::printf("Part 1 : %u\n", boarding_passes.back()); std::printf("Part 2 : %u\n", my_seat_id(boarding_passes)); }

Dold text

HÀr med den uppenbara optimeringen att tolka indata som binÀrkodning. Sorterar man sedan biljetterna efter ID blir bÄde del 1 och del 2 trivial. Det mest utrymmeskrÀvande i hela den hÀr lösningen Àr att lÀsa in filen...

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

PermalÀnk
Datavetare ★
●
Skrivet av Mordekai:

Dagens lösning exklusive FileIO tog nog 1ms oavsett sprÄk, lösning, processor men det vore kul att se exekveringstid exklusive FileIO pÄ lösningarna.

Gjorde en check pĂ„ mitt program, tar 0,69 ms vilket inte Ă€ndras pĂ„ nĂ„got relevant sĂ€tt vare sig man lĂ€ser in filen frĂ„n disk eller kompilerar in den direkt i programmet. Är mer IPC som Ă€r kasst, fĂ„r bara 1,13 i IPC pĂ„ en i7-8559U (skulle vara kul att veta vad Apple Firestorm fĂ„r, men har inte hittat nĂ„gra verktyg som kan mĂ€ta antal spenderade cykler/instruktioner Ă€n)

kjonsson@bean:~/AoC/advent-of-code-2020/day5$ sudo perf stat ./day5 Part 1 : 904 Part 2 : 669 Performance counter stats for './day5': 0,686254 task-clock (msec) # 0,815 CPUs utilized 0 context-switches # 0,000 K/sec 0 cpu-migrations # 0,000 K/sec 115 page-faults # 0,168 M/sec 2 801 283 cycles # 4,082 GHz 3 154 994 instructions # 1,13 insn per cycle 542 754 branches # 790,894 M/sec 18 454 branch-misses # 3,40% of all branches 0,000841584 seconds time elapsed

Byggt med clang++ med -O2 -march=native
Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

PermalÀnk
Medlem ★
●
Skrivet av Yoshman:

Gjorde en check pĂ„ mitt program, tar 0,69 ms vilket inte Ă€ndras pĂ„ nĂ„got relevant sĂ€tt vare sig man lĂ€ser in filen frĂ„n disk eller kompilerar in den direkt i programmet. Är mer IPC som Ă€r kasst, fĂ„r bara 1,13 i IPC pĂ„ en i7-8559U (skulle vara kul att veta vad Apple Firestorm fĂ„r, men har inte hittat nĂ„gra verktyg som kan mĂ€ta antal spenderade cykler/instruktioner Ă€n)

kjonsson@bean:~/AoC/advent-of-code-2020/day5$ sudo perf stat ./day5 Part 1 : 904 Part 2 : 669 Performance counter stats for './day5': 0,686254 task-clock (msec) # 0,815 CPUs utilized 0 context-switches # 0,000 K/sec 0 cpu-migrations # 0,000 K/sec 115 page-faults # 0,168 M/sec 2 801 283 cycles # 4,082 GHz 3 154 994 instructions # 1,13 insn per cycle 542 754 branches # 790,894 M/sec 18 454 branch-misses # 3,40% of all branches 0,000841584 seconds time elapsed

Byggt med clang++ med -O2 -march=native

Skumt, att lÀsa in filen frÄn disk tar mig 45ms, Samsung 970 Pro.
EDIT
lol sorry, hade ingen hÄrdkodad sökvÀg... stegar igenom lite katalogstruktur.
EDIT2
Tog 7 millisekunder med hÄrdkodad sökvÀg. Det Àr ju dock en .Net funktion som splittar linjer till en array.

Fel av mig
PermalÀnk
Datavetare ★
●
Skrivet av Mordekai:

Skumt, att lÀsa in filen frÄn disk tar mig 45ms, Samsung 970 Pro.
EDIT
lol sorry, hade ingen hÄrdkodad sökvÀg... stegar igenom lite katalogstruktur.
EDIT2
Tog 7 millisekunder med hÄrdkodad sökvÀg. Det Àr ju dock en .Net funktion som splittar linjer till en array.

Nu kör vi olika CPU, olika sprÄk och framförallt olika OS. Detta Àr samma test fast med exakt den kod jag postade ovan, d.v.s. man lÀser in data rad för rad via C++ standardbibliotek. Man spenderar dÄ 0,77 ms i processen

kjonsson@bean:~/AoC/advent-of-code-2020/day5$ sudo perf stat ./day5 Part 1 : 904 Part 2 : 669 Performance counter stats for './day5': 0,765458 task-clock (msec) # 0,837 CPUs utilized 0 context-switches # 0,000 K/sec 0 cpu-migrations # 0,000 K/sec 118 page-faults # 0,154 M/sec 3 123 889 cycles # 4,081 GHz 3 459 350 instructions # 1,11 insn per cycle 599 518 branches # 783,215 M/sec 19 851 branch-misses # 3,31% of all branches 0,000914872 seconds time elapsed

Dold text
Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

PermalÀnk
Medlem ★
●

Gick inte speciellt bra nu, men jag pÄminde för mig sjÀlv att det inte var meningen att detta skulle vara lÀtt. Hade problem med mina flotta lowerHalf och upperHalf metoder tills jag gav upp och tjuvade frÄn nÄgon av er. DÄ insÄg jag att jag försökte för mycket, att det rÀckte med en sÄdan trivial algoritm och att en int avrundades nerÄt automatiskt. Allt annat skrev jag iaf sjÀlv...

Dag: 5
SprÄk: Kotlin
Lösning: GitHub

Visa signatur

| Mobo: Gigabyte X570 GAMING X | CPU: AMD Ryzen 9 3900X + Dark Rock 4 | RAM: 32GB @ 3000MHz | GPU: Gigabyte RTX 3080 OC | PSU: Seasonic GX 850W | Chassi: NZXT S340 Elite Matte Black | M.2: Samsung 970 Evo 500GB & 1000GB | HDD: 4TB | Monitors: Acer Predator X34 GS & Acer XB270HU |

PermalÀnk
Medlem ★
●

Go börjar vÀl vÀxa lite pÄ en, vill kunna bidra till OpenDiablo2, sÄ lyckas jag traggla igenom hela advent of code med ett sprÄk man aldrig rört tidigare sÄ kanske man lÀr sig tillrÀckligt för att hoppa pÄ och hjÀlpa...

Dag: 5
SprÄk: Go
Lösning:

func main() { passes := myIo() highest := 0 var seatIds []int for _, v := range passes { result := calcSeat(v) seatIds = append(seatIds, result) if result > highest { highest = result } } fmt.Println("Highest seat ID: ", highest) sort.Ints(seatIds) previous := seatIds[0] - 1 for _, v := range seatIds { fmt.Print(" ID: ", v) if v != previous+1 { fmt.Println("Found missing seat at: ", previous+1) } previous = v } } func calcSeat(pass string) int { rowPart := pass[0:7] rowMax := 127 rowMin := 0 for _, v := range rowPart { if string(v) == "F" { rowMax = (rowMin + rowMax) / 2 } else if string(v) == "B" { rowMin = (rowMin + rowMax + 1) / 2 } } colMax := 7 colMin := 0 colPart := pass[7:10] for _, v := range colPart { if string(v) == "L" { colMax = (colMin + colMax) / 2 } else if string(v) == "R" { colMin = (colMin + colMax + 1) / 2 } } return ((rowMax+rowMin)/2)*8 + ((colMax + colMin) / 2) }

Dold text

Dag: 4
SprÄk: Go
Lösning:

func day4() { f, err := os.Open("files\\day4") if err != nil { log.Fatal(err) } defer f.Close() scanner := bufio.NewScanner(f) var passports []string var temp string for scanner.Scan() { temp += scanner.Text() temp += " " if len(scanner.Text()) <= 0 { passports = append(passports, temp) temp = "" } } if err := scanner.Err(); err != nil { log.Fatal(err) } required := []string{"byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"} var validPassports []passport.Passport count := 0 for _, v := range passports { valid := true for _, vv := range required { if !strings.Contains(v, vv) { valid = false } } if valid { count++ split := strings.Split(v, " ") newPassport := passport.Passport{ Byr: getWhereName(split, "byr"), Iyr: getWhereName(split, "iyr"), Eyr: getWhereName(split, "eyr"), Hgt: getWhereName(split, "hgt"), Hcl: getWhereName(split, "hcl"), Ecl: getWhereName(split, "ecl"), Pid: getWhereName(split, "pid"), } validPassports = append(validPassports, newPassport) } } validCount := 0 for _, v := range validPassports { if v.Valid() { fmt.Println(v.ToString()) validCount++ } } fmt.Println("Amount of passports:", len(passports), "Amount of first part valid passports:", count) fmt.Println("Second part validated passports amount:", validCount) } func getWhereName(p []string, which string) string { for _, v := range p { if which == getLeftside(v) { return getRightside(v) } } return "" } func getLeftside(val string) string { return strings.Split(val, ":")[0] } func getRightside(val string) string { return strings.Split(val, ":")[1] } type Passport struct { Byr string Iyr string Eyr string Hgt string Hcl string Ecl string Pid string } func (p Passport) ToString() string { return "Byr: " + p.Byr + " Iyr: " + p.Iyr + " Eyr: " + p.Eyr + " Hgt: " + p.Hgt + " Hcl: " + p.Hcl + " Ecl: " + p.Ecl + " Pid: " + p.Pid } func (p Passport) Valid() bool { return validateBirthyear(p.Byr) && validateIssueyear(p.Iyr) && validateExpyear(p.Eyr) && validateHeight(p.Hgt) && validateHaircolor(p.Hcl) && validateEyecolor(p.Ecl) && validatePassportId(p.Pid) } func validateBirthyear(val string) bool { convert, _ := strconv.Atoi(val) return convert >= 1920 && convert <= 2002 } func validateIssueyear(val string) bool { convert, _ := strconv.Atoi(val) return convert >= 2010 && convert <= 2020 } func validateExpyear(val string) bool { convert, _ := strconv.Atoi(val) return convert >= 2020 && convert <= 2030 } func validateHeight(val string) bool { pattern := `^(\d+)(cm|in)$` compiledRegex := regexp.MustCompile(pattern) submatches := compiledRegex.FindAllStringSubmatch(val, -1) if submatches == nil { return false } convert, _ := strconv.Atoi(submatches[0][1]) if submatches[0][2] == "cm" { return convert >= 150 && convert <= 193 } else if submatches[0][2] == "in" { return convert >= 59 && convert <= 76 } else { return false } } func validateHaircolor(val string) bool { pattern := `^[#a-f0-9]{7}$` compiledRegex := regexp.MustCompile(pattern) if compiledRegex.FindString(val) == "" { return false } else { return true } } func validateEyecolor(val string) bool { valid := []string{"amb", "blu", "brn", "gry", "grn", "hzl", "oth"} for _, v := range valid { if strings.Contains(val, v) { return true } } return false } func validatePassportId(val string) bool { pattern := `^[0-9]{9}$` compiledRegex := regexp.MustCompile(pattern) if compiledRegex.FindString(val) == "" { return false } else { return true } }

Dold text
Visa signatur

AW3423DW QD-OLED - Ryzen 5800x - MSI Gaming Trio X 3090 - 64GB 3600@cl16 - Samsung 980 Pro 2TB/WD Black SN850 2TB

PermalÀnk
Medlem ★
●
Skrivet av GLaDER:

Dag: 5
SprÄk: Go
Lösning: GitHub

Glöm inte att kika in pÄ vÄr leaderboard: 115994-59705230

Kul! Till skillnad frÄn igÄr var det hÀr en uppgift med lite parsande och mycket tÀnkande. Jag skÀms dock lite nÀr jag tÀnker pÄ vad min algoritmlÀrare frÄn universitetet skulle sÀga om han tittat över axeln pÄ mig medans jag trevade fram en lösning. Det hÀr var en uppgift i min smak, men Àndock klurig.

Dold text

Dag: 6
SprÄk: Go
Lösning: GitHub

Glöm inte att kika in pÄ vÄr leaderboard: 115994-59705230

Idag fick jag brottas med hur Golang hanterar whitespace nÀr man itererar över en strÀng. Inga konstigheter frÄn sprÄkets sida, egentligen, men jag blev ÀndÄ tagen lite pÄ sÀngen och fick lÀgga nÄgra extra minuter pÄ att förstÄ varför jag fick fel svar.

DÀrtill spenderade jag en del tid pÄ att leta igenom standardbiblioteket strings efter funktioner av sorten unique(), set(), eller liknande, men hittade inget. IstÀllet gav jag mig pÄ att bygga min egna variant.

Blev dock vÀldigt nöjd nÀr Part 2 gick att lösa med en vÀldigt enkel extension av min egensnickrade uniqueRunes()!

Dold text
Visa signatur

:(){ :|:& };:

đŸŠđŸ»â€â™‚ïž   đŸšŽđŸ»â€â™‚ïž   đŸƒđŸ»â€â™‚ïž   ☕

PermalÀnk
Medlem
●

Dag 6 Scala:

import ammonite.ops._ val groups = (read! pwd/"input.txt").split("\\n\\n").map(_.split("\\s+") groups.map(_.flatten.distinct.size).sum //Uppgift 1 groups.map{ (group) => group.flatten.groupBy(identity).count { case(_k,v) => v.size == group.size }}.sum //Uppgift 2

Eller om jag skulle skriva lite mer maintainable kod som jag inte skulle vilja slÄ ihjÀl mig sjÀlv om jag kom tillbaka till för att fixa en bugg i en vecka senare. Inklusive kommentarer för dom som inte kan Scala:

def count(group: Array[String]): Int = { //För input Array("ab", "ac") gör jag flatten sÄ vi fÄr Array('a','b','a','c') //groupBy omvandlar till Map och funktionen vi skickar in berÀttar hur man vÀljer nyckel. // "identity" Àr inbyggd, det Àr (x) => x funktionen. //SÄ nu fÄr vi exvis: Map('a' -> Array('a', 'a'), 'b' -> Array('b'), 'c' -> Array('c')) val map:Map[Char,Array[Char]] = group.flatten.groupBy(identity) //RÀkna hur mÄnga entries som alla svarat pÄ, exvis Map('a' -> Array('a', 'a') map.count { case(_key, valueArray) => valueArray.size == group.size } } } //Mappa sÄ vi omvandlar vÄr Array frÄn att innehÄlla Arrays av String till att vara en Array of Int. Summera innehÄllet i Arrayen. groups.map(count).sum

Kom pÄ att en sak som kan vara lite förvirrande Àr att jag anvÀnder lite olika sÀtt att referera till funktioner. I Scala kan man för exvis map skriva:

val l = List("hej", "hopp") //variabeln l Àr List[String] men det behöver jag inte skriva, det infereras. l.map( (s: String) => s.size) //Ger oss List(3, 4). Detta kan Àven skrivas som: l.map(_.size) //Underscore placeholder shortcut, Scala vet att det Àr en List[String] sÄ kan anvÀnda String metoder pÄ _ //Eller om vi har en funktionsreferens kan vi skicka in den direkt till map, Scala matchar in parametrarna och deras typer. //Identity finns i PreDef sÄ den Àr alltid tillgÀnglig: https://www.scala-lang.org/api/current/scala/Predef$.html#ide... l.map(identity) //Returnerar List("hej", "hopp") inte ovÀntat. //Och om man vill pattern matcha pÄ tupler - det hÀr slet jag lÀnge med innan jag hittade rÀtt lösning //första gÄngen. Blir enkel kod men lite komplicerad typteori under. val tuples = List(("foo",1),("bar", 2)) tuples.map ( (a,b) => ..) //detta kompilerar inte, map metoden krÀver alltid en funktion som tar en parameter, inte tvÄ. tuples.map { (a) => val stringPart = a._1 //Enda stÀllet med one-based indexing i sprÄket. Mycket irriterande. val intPart = a._2 } //Kompilerar, men kÀnns pratigt. //Pattern matching to the rescue. Nu slipper vi se 1-indexing ocksÄ. //Det innanför mÄsvingarna omvandlas till en PartialFunction[A,B] som alltsÄ matchar parametern som behövs för map. tuples.map { case(stringPart, intPart) => ... }

Dold text
Buggfix :). Lite mera Scala förklaring.
PermalÀnk
Medlem
●

Dag: 6
SprÄk: Golang
Lösning:

package main import ( "bufio" "fmt" "os" ) type VoteGroup struct { Votes map[string]int Persons int } func getVotesPartOne(rows []string) int { result := 0 voteGroup := VoteGroup{Votes: map[string]int{}} for _, row := range rows { if len(row) == 0 { result += len(voteGroup.Votes) voteGroup = VoteGroup{Votes: map[string]int{}} continue } for _, char := range row { voteGroup.Votes[string(char)]++ } } result += len(voteGroup.Votes) return result } func getVotesPartTwo(rows []string) int { result := 0 voteGroup := VoteGroup{Votes: map[string]int{}} for _, row := range rows { if len(row) == 0 { result += matchVoteCountPersons(voteGroup) voteGroup = VoteGroup{Votes: map[string]int{}} continue } for _, char := range row { voteGroup.Votes[string(char)]++ } voteGroup.Persons++ } result += matchVoteCountPersons(voteGroup) return result } func matchVoteCountPersons(voteGroup VoteGroup) int { count := 0 for _, numberOfVotes := range voteGroup.Votes { if voteGroup.Persons == numberOfVotes { count++ } } return count } func getRows(filename string) []string { file, _ := os.Open(filename) defer file.Close() scanner := bufio.NewScanner(file) var rows []string for scanner.Scan() { rows = append(rows, scanner.Text()) } return rows } func main() { rows := getRows("../input.txt") fmt.Println("PartOne", getVotesPartOne(rows)) fmt.Println("PartTwo", getVotesPartTwo(rows)) }

Dold text
Fel dag..
PermalÀnk
Medlem ★
●
Skrivet av Yoshman:

HÀr med den uppenbara optimeringen att tolka indata som binÀrkodning. Sorterar man sedan biljetterna efter ID blir bÄde del 1 och del 2 trivial. Det mest utrymmeskrÀvande i hela den hÀr lösningen Àr att lÀsa in filen...

Har du lust att förklara hur och varför man kan tolka detta som ett binÀrt tal och sedan omvandla det till ett decimalt? Inte riktigt förstÄtt mig pÄ det till fullo efter lite googlingar

PermalÀnk
Medlem ★
●

Dag: 6
SprÄk: VB.Net

Imports System.IO Module Program Sub Main(args As String()) Dim partOneCount As Integer = 0 Dim partTwoCount As Integer = 0 Using reader As New StreamReader("input.txt") While Not reader.EndOfStream Dim groupAnswers As String = "" Dim groupMemberCount As Integer = 0 Dim line = reader.ReadLine() While Not String.IsNullOrWhiteSpace(line) groupMemberCount += 1 groupAnswers += line line = reader.ReadLine() End While Dim anyoneYes As New HashSet(Of Char) For i = 0 To groupAnswers.Length - 1 anyoneYes.Add(groupAnswers(i)) Next partOneCount += anyoneYes.Count For Each question In anyoneYes If groupMemberCount = groupAnswers.Count(Function(q) q = question) Then partTwoCount += 1 End If Next End While End Using Console.WriteLine("Part 1: " & partOneCount.ToString()) Console.WriteLine("Part 2: " & partTwoCount.ToString()) End Sub End Module

Dold text
PermalÀnk
Medlem ★
●

Dag: 6
SprÄk: c#

Kör numera i LINQPad.

var input = File .ReadAllText("day-06.txt") .Split(new[] { "\n\n" }, StringSplitOptions.RemoveEmptyEntries) .Select(x => x.Split('\n')) .ToArray(); var part1 = input.Sum(x => x.SelectMany(y => y).Distinct().Count()); var part2 = input.Sum(x => x.First().Count(y => x.All(z => z.Contains(y))));

Dold text
PermalÀnk
●

Dag: 6
SprÄk: Nim
Lösning: Github

Dagens kÀndes som att det var mer straightforward Àn igÄr iaf

PermalÀnk
Medlem ★
●

Dag 6, Python one-liner + Python, inte fullt sÄ komplex och med kommentarer.

# The one-liner print(*[sum([len(a) for a in [operation(*sets) for sets in [[set([letter for letter in line]) for line in group] for group in [group.split('\n') for group in open("input", "r").read().split('\n\n')]]]]) for operation in [set.union, set.intersection]]) # The slightly less convoluted solution :) # Read the whole file, split into one string per group groups = [group.split('\n') for group in open("input", "r").read().split('\n\n')] # Build a list, per group, with sets of letters per line in the group letters_per_group = [[set([letter for letter in line]) for line in group] for group in groups ] # Use the set union operation to find the letters that are in *any* of the lines any = [set.union(*sets) for sets in letters_per_group] # Use the set intersection operation to find the letters that are in *all* of the lines all = [set.intersection(*sets) for sets in letters_per_group] # Add the number of members in the all/any sets print(sum([len(a) for a in any]), sum([len(a) for a in all]))

Dold text
PermalÀnk
Datavetare ★
●
Skrivet av noyce:

Har du lust att förklara hur och varför man kan tolka detta som ett binÀrt tal och sedan omvandla det till ett decimalt? Inte riktigt förstÄtt mig pÄ det till fullo efter lite googlingar

Blev ett syftningsfel, att det kan ses som ett binÀrtal Àr kanske inte inte uppenbart, men nÀr man ser det Àr utnyttjandet av detta en uppenbar optimering.

Om vi tar strÀngen 'FFBFBFBRRL' och sedan kollar in @Ingetledigtnamn namns extremt kompakta lösning, specifikt delen med "translate"

>>> 'FFBFBFBRRL'.translate({70:48,66:49,82:49,76:48}) '0010101110'

D.v.s. 'F' och 'L' översÀtts till '0', 'B' och 'R' till '1'.

Varför kan man göra det? TÀnkt ett 3 bitar tal. Högsta biten avgör om slutresultatet blir 0-3 (bit#2 slÀkt) eller 4-7 (bit#2 tÀnd). Ignorerar man sedan bit#2 och tittar pÄ bit#1 avgör den om slutresultatet hamnar inom 0-1 eller 2-3. etc.

Om det Àr sjÀlva översÀttandet (anvÀndning och argument till translate kanske?) som Àr problemet, motsvarande i JS dÀr översÀttningen kanske Àr mer explicit

> 'FFBFBFBRRL'.split('').map(ch => ch == 'B' || ch == 'R' ? '1' : '0').join('') '0010101110'

I uppgiften avgör första tecknet om du sitter i bakre halvan eller frÀmre halvan. NÀr du vet halva avgör andra tecknet om du sitter i frÀmre eller bakre delen av den halva du hamnat i etc. De sista tre tecknet avgöra bara samma sak i sidled.

StrÀngen med ettor-och-nollar man fÄr ut Àr plats-ID om det tolkas som ett binÀrt tal.

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

PermalÀnk
Medlem
●

Dag: 6
SprÄk: Powershell
Lösninig: Github

Kör pÄ min egna vÀg.
Del 2 kÀnner jag att den blev sjukt onödigt komplex. Detta var pga jag inte fick splitten att fungera som jag tÀnkte.
Klurade dock ut det sen men vet inte varför just den kombon fungerade.

tyckte att -split '\r\n' borde fungera. testa \n mm men nedan fick det att gruppera in dem som jag ville.
KÀnns som att det blir nÄgot vajsing nÀr jag kopierar in det och sparar det via vscode.

((Get-Content -Path .\Day6\part6.txt -raw) -split '\n\r').trim()

Sen att Sets vore en bÀttre lösning. SÄ kommer nog snickra pÄ en sÄdan med.

Dold text
Visa signatur

Vad vore vÀrlden utan silvertejp?

PermalÀnk
Medlem ★
●
Skrivet av Yoshman:

Blev ett syftningsfel, att det kan ses som ett binÀrtal Àr kanske inte inte uppenbart, men nÀr man ser det Àr utnyttjandet av detta en uppenbar optimering.

Om vi tar strÀngen 'FFBFBFBRRL' och sedan kollar in @Ingetledigtnamn namns extremt kompakta lösning, specifikt delen med "translate"

>>> 'FFBFBFBRRL'.translate({70:48,66:49,82:49,76:48}) '0010101110'

D.v.s. 'F' och 'L' översÀtts till '0', 'B' och 'R' till '1'.

Varför kan man göra det? TÀnkt ett 3 bitar tal. Högsta biten avgör om slutresultatet blir 0-3 (bit#2 slÀkt) eller 4-7 (bit#2 tÀnd). Ignorerar man sedan bit#2 och tittar pÄ bit#1 avgör den om slutresultatet hamnar inom 0-1 eller 2-3. etc.

Om det Àr sjÀlva översÀttandet (anvÀndning och argument till translate kanske?) som Àr problemet, motsvarande i JS dÀr översÀttningen kanske Àr mer explicit

> 'FFBFBFBRRL'.split('').map(ch => ch == 'B' || ch == 'R' ? '1' : '0').join('') '0010101110'

I uppgiften avgör första tecknet om du sitter i bakre halvan eller frÀmre halvan. NÀr du vet halva avgör andra tecknet om du sitter i frÀmre eller bakre delen av den halva du hamnat i etc. De sista tre tecknet avgöra bara samma sak i sidled.

StrÀngen med ettor-och-nollar man fÄr ut Àr plats-ID om det tolkas som ett binÀrt tal.

Tack. Det som förvirrade mig var nog hur man kopplade det till deras funktion för berÀkning av id:t. Dvs

row * 8 + col = x

Vilket dÄ förklaras av att man gör en vÀnsterskift med 3? DÀrav ökar "vÀrdet" med 8 för raderna.

Om man bortser frÄn kolumnerna sÄ Àr det alltsÄ:

FBFBBFF 0101100 ---------- 44 0101100 << 3 (Är det sĂ„ man skriver?) -------------- = 0101100000 -------------- = 352

Skiftar man dÄ istÀllet in kolumnerna istÀllet för 0:or, alltsÄ 101 (= 5)

01011000101 --------------- = 356 // eller 0000000101 + 0101100000 ------------------ 01011000101 ------------------ = 356

PermalÀnk
Datavetare ★
●

Dag: 6
SprÄk: Swift
Lösning: GitHub

Bra uppgift om man lÀr ett nytt sprÄk, fick lÀsa pÄ lite om Set<T> i Swift inför denna.

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

PermalÀnk
Datavetare ★
●
Skrivet av noyce:

Tack. Det som förvirrade mig var nog hur man kopplade det till deras funktion för berÀkning av id:t. Dvs

row * 8 + col = x

Vilket dÄ förklaras av att man gör en vÀnsterskift med 3? DÀrav ökar "vÀrdet" med 8 för raderna.

Om man bortser frÄn kolumnerna sÄ Àr det alltsÄ:

FBFBBFF 0101100 ---------- 44 0101100 << 3 (Är det sĂ„ man skriver?) -------------- = 0101100000 -------------- = 352

Skiftar man dÄ istÀllet in kolumnerna istÀllet för 0:or, alltsÄ 101 (= 5)

01011000101 --------------- = 356 // eller 0000000101 + 0101100000 ------------------ 01011000101 ------------------ = 356

Kurvbollen hÀr Àr att uppgiften separerar det i rader och kolumner. Plats-ID Àr en endimensionell egenskap i detta fall, bara sÄ att man lagt kolumner i de tre minst signifikanta bitarna medan rader Àr de mest signifikanta sju bitarna (tio bitar, sÄ rÀtt stort plan).

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

PermalÀnk
Medlem ★
●

Dag 6
C#

public static string Run1(string inputData,bool test = false) { inputData = inputData.Replace("\r", ""); string[] groups = inputData.Split("\n\n", StringSplitOptions.RemoveEmptyEntries); int[] answers = new int[26]; int sumgroupanswers = 0; foreach (string group in groups) { int groupanswers = 0; for (int i = 0; i < answers.Length; i++) { answers[i] = 0; } string[] persons = group.Split("\n", StringSplitOptions.RemoveEmptyEntries); foreach (string person in persons) { byte[] asciiBytes = Encoding.ASCII.GetBytes(person); foreach (byte bytechar in asciiBytes) { int index = (int)bytechar - 97; answers[index] = 1; } } for (int i = 0; i < answers.Length; i++) { groupanswers=groupanswers + answers[i]; } sumgroupanswers = sumgroupanswers + groupanswers; } return sumgroupanswers.ToString(); } public static string Run2(string inputData, bool test = false) { inputData = inputData.Replace("\r", ""); string[] groups = inputData.Split("\n\n", StringSplitOptions.RemoveEmptyEntries); int[] answers = new int[26]; int sumgroupanswers = 0; foreach (string group in groups) { int groupanswers = 0; for (int i = 0; i < answers.Length; i++) { answers[i] = 0; } string[] persons = group.Split("\n", StringSplitOptions.RemoveEmptyEntries); foreach (string person in persons) { byte[] asciiBytes = Encoding.ASCII.GetBytes(person); foreach (byte bytechar in asciiBytes) { int index = (int)bytechar - 97; answers[index] = answers[index]+1; } } for (int i = 0; i < answers.Length; i++) { if (answers[i]==persons.Length) { groupanswers = groupanswers + 1; } } sumgroupanswers = sumgroupanswers + groupanswers; } return sumgroupanswers.ToString(); }

Dold text
PermalÀnk
Medlem
●

Dag 6, rÀtt sÄ klurigt idag, blev mycket googlande
C#

class Program { static List<string> input = File.ReadAllLines("input.csv").ToList(); static void Main(string[] args) { input.Add(" "); Console.WriteLine(PartOne()); Console.WriteLine(PartTwo()); Console.ReadLine(); } static int PartOne() { int people = 0; string entry = ""; int yes = 0; int result = 0; for (int i = 0; i < input.Count; i++) { if (!String.IsNullOrWhiteSpace(input[i])) { people++; entry = entry + input[i]; } if (String.IsNullOrWhiteSpace(input[i])) { yes = entry.Distinct().Count(); entry = ""; } result += yes; yes = 0; } return result; } static int PartTwo() { int people = 0; string entry = ""; int yes = 0; int result = 0; char a = ' '; for (int i = 0; i < input.Count; i++) { if (!String.IsNullOrWhiteSpace(input[i])) { people++; entry = entry + input[i]; } if (String.IsNullOrWhiteSpace(input[i])) { for (int j = 97; j < 123; j++) { a = (char)j; string b = a.ToString(); if (Regex.Matches(entry, b).Count == people) yes++; } entry = ""; people = 0; } result += yes; yes = 0; } return result; } }

Dold text
PermalÀnk
Medlem ★
●

Dag 6

JavaScript

Brukar inte skriva ren JS, TS som gÀller annars.
(Ja, lite anti-pattern med &&, men kort o gott. )

const dataSet = ` abc a b c ab ac a a a a b` const alts = ["a", "b", "c", "x", "y", "z"] let result = 0 dataSet.split(/\n\n/).forEach((group) => alts.forEach((alt) => group.indexOf(alt) !== -1 && result++)) console.log(result)

Dold text
PermalÀnk
Medlem ★
●

Inte helnöjd med dagens lösning, men set-operationer Àr vÀl inte awks styrka.

part1$ <in sed 's/^$/@/' | tr '\n' ' ' | tr '@' '\n' | tr -d ' ' | awk '{ split("", c); split($0, a, ""); for (i in a) { c[a[i]] } r += length(c) } END { print r }' part2$ <in sed 's/^$/@/' | tr '\n' ' ' | tr '@' '\n' | awk '{ split("", q); for (i = 1; i <= NF; i++) { split($i, a, ""); for (j in a) { if (++q[a[j]] == NF) { print } } } }' | wc -l

Dold text
Visa signatur

"Some poor, phoneless fool is probably sitting next to a waterfall somewhere, totally unaware of how angry and scared he's supposed to be." - Duncan Trussell