Citera sÄ hittar jag tillbaks och kan ge svar.
đ Advent of Code (AoC) 2022 đ
Dag: 4
SprÄk: Dyalog APL
a bâ1 0 1 0âââšš'\d+'âS'&'šââNGET'4.txt' 1
+/0â„Ă/a-b â del1
+/0â„Ă/a-âœb â del2
APL interpreteras frÄn höger till vÀnster.
'\d+'âS'&'šââNGET'4.txt'1
LĂ€ser in filen, regex plockar ut siffrorna
ââšš'\d+'âS'&'šââNGET'4.txt'1
⚠Tolkar om sifforna frÄn text till nummer, resultatet Àr en array fylld med fyra elements arrayer
â Gör om arrayen till en 1000x4 matris
1 0 1 0âââšš'\d+'âS'&'šââNGET'4.txt' 1
X â Y "Partitioned Enclose" delar upp arrayen Y enligt X.
Resultatet Àr en array innehÄllande tvÄ 1000x2 matriser. En matris per range.
a bâ1 0 1 0âââšš'\d+'âS'&'šââNGET'4.txt' 1
Tilldelar variabeln a första matrisen och b den andra.
a-b
matris a - matris b vilket Àr samma sak som (range A start - range B start) (range A end - range B end)
Ă/a-b
Radvis reduce med multiplikation = (range A start - range B start) * (range A end - range B end)
Resultatet Àr en 1000 elements vektor. Reduce minskar arrayens/matrisens rank (dimensioner) med 1
0â„Ă/a-b
JÀmför alla element i vektorn med 0. Alla element som Àr negativa eller 0 sÀtts till 1
+/0â„Ă/a-b
+/ plus reduce Summerar vektorn vilket ger svaret
+/0â„Ă/a-âœb
Samma som del1 men âœb byter plats pĂ„ kolumnerna i matris b. (range A start - range B end) * (range A end - range B start)
Skrev Àven en vektoriserad version i Scala men gissningsvis genererar JIT-kompilatorn hyffsat bra kod ÀndÄ. Inte hunnit jÀmföra Ànnu.
Tog inte med fil io eller parsning. (as/bs = range a start/end, cs/ds = range b start/end)
BerÀknar del1 och del2 samtidigt. SIMD bitar / 16 element Ät gÄngen.
Programmet Àr lÄngsamt pÄ den vÀldigt korta input man fÄr frÄn AoC.
def day4(as: Array[Short], bs: Array[Short], cs: Array[Short], ds: Array[Short]): (Int, Int) =
val spec = ShortVector.SPECIES_PREFERRED
val sz = as.length
var i = 0
var acc1v = ShortVector.zero(spec)
var acc2v = ShortVector.zero(spec)
while i < spec.loopBound(sz) do
val av = ShortVector.fromArray(spec, as, i)
val bv = ShortVector.fromArray(spec, bs, i)
val cv = ShortVector.fromArray(spec, cs, i)
val dv = ShortVector.fromArray(spec, ds, i)
acc1v = acc1v.add(av.sub(bv).mul(bv.sub(dv)).compare(LE, 0).toVector.abs())
acc2v = acc2v.add(av.sub(dv).mul(bv.sub(cv)).compare(LE, 0).toVector.abs())
i += spec.length()
var acc1s = 0
var acc2s = 0
while i < sz do
if (as(i) - cs(i)) * (bs(i) - ds(i)) <= 0 then acc1s += 1
if (as(i) - ds(i)) * (bs(i) - cs(i)) <= 0 then acc2s += 1
i += 1
(acc1v.reduceLanes(ADD) + acc1s, acc2v.reduceLanes(ADD) + acc2s)
Dag:1 del1
SprÄk: Go
Lösning:
package main
import (
"fmt"
"os"
"strconv"
"strings"
)
func main() {
var elf []int
input, _ := os.ReadFile("../input.txt")
inputString := string(input)
inputArray := strings.Split(inputString, "\n\n")
for i := 1; i <= len(inputArray); i++ {
var elfCal int
calories := strings.Split(inputArray[i-1], "\n")
for j := 0; j < len(calories); j++ {
calInt, _ := strconv.Atoi(calories[j])
elfCal += calInt
}
elf = append(elf, elfCal)
elfCal = 0
}
maxElf := 0
for i := 0; i < len(elf); i++ {
if elf[i] > maxElf {
maxElf = elf[i]
}
}
fmt.Println(maxElf)
}
Dag:1 del2
SprÄk: Go
Lösning:
package main
import (
"fmt"
"os"
"strconv"
"strings"
)
func main() {
var elf []int
input, _ := os.ReadFile("../input.txt")
inputString := string(input)
inputArray := strings.Split(inputString, "\n\n")
for i := 1; i <= len(inputArray); i++ {
var elfCal int
calories := strings.Split(inputArray[i-1], "\n")
for j := 0; j < len(calories); j++ {
calInt, _ := strconv.Atoi(calories[j])
elfCal += calInt
}
elf = append(elf, elfCal)
elfCal = 0
}
maxElf := 0
secondElf := 0
thirdElf := 0
for i := 0; i < len(elf); i++ {
if elf[i] > maxElf {
maxElf = elf[i]
}
}
for i := 0; i < len(elf); i++ {
if elf[i] > secondElf && elf[i] < maxElf {
secondElf = elf[i]
}
}
for i := 0; i < len(elf); i++ {
if elf[i] > thirdElf && elf[i] < secondElf {
thirdElf = elf[i]
}
}
topThree := maxElf + secondElf + thirdElf
fmt.Println(topThree)
}
Dag:2 del1
SprÄk: Go
Lösning:
package main
import (
"fmt"
"os"
"strings"
)
func main() {
input, _ := os.ReadFile("../input.txt")
inputString := string(input)
rounds := strings.Split(inputString, "\n")
var score int
for i := 0; i < len(rounds); i++ {
oponent := rounds[i][0]
mine := rounds[i][2]
switch mine {
//I throw rock
case 'X':
score += 1
//I throw paper
case 'Y':
score += 2
//I throw scissors
case 'Z':
score += 3
}
switch oponent {
//They throw Rock
case 'A':
if mine == 'X' {
score += 3
}
if mine == 'Y' {
score += 6
}
if mine == 'Z' {
score += 0
}
//They throw Paper
case 'B':
if mine == 'X' {
score += 0
}
if mine == 'Y' {
score += 3
}
if mine == 'Z' {
score += 6
}
//They throw Scissors
case 'C':
if mine == 'X' {
score += 6
}
if mine == 'Y' {
score += 0
}
if mine == 'Z' {
score += 3
}
}
}
fmt.Println(score)
}
Dag:2 del2
SprÄk: Go
Lösning:
package main
import (
"fmt"
"os"
"strings"
)
func main() {
input, _ := os.ReadFile("../input.txt")
inputString := string(input)
rounds := strings.Split(inputString, "\n")
var score int
for i := 0; i < len(rounds); i++ {
oponent := rounds[i][0]
mine := rounds[i][2]
switch mine {
//I throw rock
case 'X':
score += 0
//I throw paper
case 'Y':
score += 3
//I throw scissors
case 'Z':
score += 6
}
switch oponent {
//They throw Rock
case 'A':
if mine == 'X' {
score += 3
}
if mine == 'Y' {
score += 1
}
if mine == 'Z' {
score += 2
}
//They throw Paper
case 'B':
if mine == 'X' {
score += 1
}
if mine == 'Y' {
score += 2
}
if mine == 'Z' {
score += 3
}
//They throw Scissors
case 'C':
if mine == 'X' {
score += 2
}
if mine == 'Y' {
score += 3
}
if mine == 'Z' {
score += 1
}
}
}
fmt.Println(score)
}
Citera sÄ hittar jag tillbaks och kan ge svar.
Dag:3 del1
SprÄk: Go
Lösning:
package main
import (
"fmt"
"os"
"strings"
)
func main() {
var backpacks []string
var priority int
//take input from file and make it a string
input, _ := os.ReadFile("../input.txt")
inputString := string(input)
//split input into each elfs calories
backpacks = strings.Split(inputString, "\n")
for i := 0; i < len(backpacks); i++ {
var prio int
comp1 := backpacks[i][0 : len(backpacks[i])/2]
comp2 := backpacks[i][len(backpacks[i])/2:]
for _, ch := range comp1 {
if strings.Contains(comp2, string(ch)) {
if ch > 97 {
prio = int(ch)
prio -= 96
} else {
prio = int(ch)
prio -= 38
}
}
}
priority += prio
}
fmt.Println(priority)
}
Dag:3 del2
SprÄk: Go
Lösning:
package main
import (
"fmt"
"os"
"strings"
)
func main() {
var backpacks []string
var priority int
iterations := 0
compare := 1
//take input from file and make it a string
input, _ := os.ReadFile("../input.txt")
inputString := string(input)
//split input into each elfs calories
backpacks = strings.Split(inputString, "\n")
for i := 0; i < len(backpacks); i += 3 {
var prio int
for _, ch := range backpacks[i] {
if string(ch) == "g" {
}
if strings.Contains(backpacks[i+1], string(ch)) {
if strings.Contains(backpacks[i+2], string(ch)) {
if ch > 97 {
prio = int(ch)
prio -= 96
} else {
prio = int(ch)
prio -= 38
}
break
}
}
}
priority += prio
compare++
if compare >= 3 {
compare = 1
}
iterations++
}
fmt.Println(priority)
}
Citera sÄ hittar jag tillbaks och kan ge svar.
Dag:4 del1
SprÄk: Go
Lösning:
package main
import (
"fmt"
"os"
"strconv"
"strings"
)
func main() {
counter := 0
//take input from file and make it a string
input, _ := os.ReadFile("../input.txt")
inputString := string(input)
pairs := strings.Split(inputString, "\n")
for i := 0; i < len(pairs); i++ {
elfs := strings.Split(pairs[i], ",")
elfOneStart, _ := strconv.Atoi(strings.Split(elfs[0], "-")[0])
elfOneEnd, _ := strconv.Atoi(strings.Split(elfs[0], "-")[1])
elfTwoStart, _ := strconv.Atoi(strings.Split(elfs[1], "-")[0])
elfTwoEnd, _ := strconv.Atoi(strings.Split(elfs[1], "-")[1])
if (elfOneStart <= elfTwoStart && elfOneEnd >= elfTwoEnd) || (elfTwoStart <= elfOneStart && elfTwoEnd >= elfOneEnd) {
counter++
}
}
fmt.Println(counter)
}
Dag:4 del2
SprÄk: Go
Lösning:
package main
import (
"fmt"
"os"
"strconv"
"strings"
)
func main() {
counter := 0
//take input from file and make it a string
input, _ := os.ReadFile("../input.txt")
inputString := string(input)
pairs := strings.Split(inputString, "\n")
for i := 0; i < len(pairs); i++ {
elfOneStart, _ := strconv.Atoi(strings.Split(strings.Split(pairs[i], ",")[0], "-")[0])
elfOneEnd, _ := strconv.Atoi(strings.Split(strings.Split(pairs[i], ",")[0], "-")[1])
elfTwoStart, _ := strconv.Atoi(strings.Split(strings.Split(pairs[i], ",")[1], "-")[0])
elfTwoEnd, _ := strconv.Atoi(strings.Split(strings.Split(pairs[i], ",")[1], "-")[1])
if (elfOneStart <= elfTwoStart && elfOneEnd >= elfTwoStart) || (elfTwoStart <= elfOneStart && elfTwoEnd >= elfOneStart) {
counter++
}
}
fmt.Println(counter)
}
Citera sÄ hittar jag tillbaks och kan ge svar.
Aj! Dagens problem var ett rejÀlt hopp upp i svÄrighetsgrad. Blev sÄ pass mycket fulkod att jag inte ens vÄgar posta hÀr innan jag gÄtt igenom ordentligt och snyggat upp.
using AoCUtils;
Console.WriteLine("Mickur's Advent of Code 2022 - Day 5!");
// Setup
var input = File.ReadAllLines("input.txt");
var stackParseComplete = false;
var instructionsBegin = 0;
var stacks1 = new List<List<char>>();
var stacks2 = new List<List<char>>();
// Parsing...
for (var i = 0; i < input.Length; i++)
{
if (stackParseComplete)
{
instructionsBegin = i + 1;
break;
}
for (var j = 0; j < input[i].Length; j++)
{
var valueIndex = j * 4 + 1;
// If valueIndex is out of range, continue.
if (valueIndex >= input[i].Length)
continue;
// If valueIndex contains an integer, we are done.
if (char.IsDigit(input[i][valueIndex]))
{
stackParseComplete = true;
break;
}
// If we are in the first loop, create a stack to work with
if (i == 0)
{
stacks1.Add(new List<char>());
stacks2.Add(new List<char>());
}
// Push value to stacks
if (input[i][valueIndex] != ' ')
{
stacks1[j].Add(input[i][valueIndex]);
stacks2[j].Add(input[i][valueIndex]);
}
}
}
for (var i = 0; i < stacks1.Count; i++)
{
stacks1[i].Reverse();
stacks2[i].Reverse();
}
// Actual instructions
for (var i = instructionsBegin; i < input.Length; i++)
{
var split = input[i].Split(' ');
var move = Parsing.FastIntParse(split[1]);
var from = Parsing.FastIntParse(split[3]);
var to = Parsing.FastIntParse(split[5]);
// Part One
for (var j = 0; j < move; j++)
{
var lastIndex = stacks1[from - 1].Count - 1;
var temp = stacks1[from - 1][lastIndex];
stacks1[from - 1].RemoveAt(lastIndex);
stacks1[to - 1].Add(temp);
}
// Part Two
for (var j = move; j > 0; j--)
{
var currIndex = stacks2[from - 1].Count - j;
var temp = stacks2[from - 1][currIndex];
stacks2[from - 1].RemoveAt(currIndex);
stacks2[to - 1].Add(temp);
}
}
// Part One: ...
var answer = "";
foreach (var stack in stacks1) answer += stack[^1];
Console.WriteLine(answer);
// Part Two: ...
answer = "";
foreach (var stack in stacks2) answer += stack[^1];
Console.WriteLine(answer);
Edit: FÄr nog duga sÄ...
CPU: 7950X 5GHz@1.1v | RAM: 32GB 6000MHz CL36 | GPU: KFAÂČ 3090 SG w/ AlphaCool Eisblock Aurora
Ljudkort: Modius + Magnius | Lurar: GoldPlanar GL2000 / Sennheiser HD 650 / Philips Fidelio X3 / Supreme CD-99
Dag: 4
SprÄk: Python 3
Lösning: GitHub
Ugh. Det hÀr var inte min morgon. FrÄn att ha varit nÀstan Top 1 000 igÄr till en bit över 8 000 idag
Snurrade bort mig totalt pÄ bÄda delarna. I del 1 försökte jag lÀnge implementera min egna issubset
-metod innan jag kom pÄ att det var just konceptet sub set jag letade efter.
I del 2 gick jag bort mig pÄ att jag började leta efter överlappet för samtliga tilldelningar, samt hur stort det totala överlappet var. Det var inte förrÀn jag lÀste igenom tredje gÄngen som jag förstod att det bara var huruvida det existerade ett överlapp för varje par som var intressant. Tyckte vÀl att över 85 000 var lite stort...
Dag: 5
SprÄk: Python 3
Lösning: GitHub
Mitt hjÀrta blöder.
Jag har ett script som lÀser in datan frÄn AoC och sparar i en fil <dag>.input
. Av nÄgon outgrundlig anledning fungerade inte scriptet för att lÀsa dagens input, men det tog lÄÄÄng tid att förstÄ varför. "Problemet" var att min parsningsfunktion fortfarande returnerade en helt rimlig parsning (och eftersom jag gjorde copy-paste pÄ test-input sÄ fick jag rÀtt pÄ test-input).
Det tog nog 20 minuter för mig att lösa uppgiften; sen tog det vÀldigt lÄng tid att fatta varför jag fick fel svar.
:(){ :|:& };:
đđ»ââïž Â đŽđ»ââïž Â đđ»ââïž Â â
Dag: 5
SprÄk: Go
package main
import (
"fmt"
"strconv"
"strings"
)
type crateStack []byte
type crateStorage []crateStack
type crateMoves struct {
cnt int
from int
to int
}
func (cStack *crateStack) push(crate byte) {
*cStack = append(*cStack, crate)
}
func (cStack *crateStack) pop() byte {
newLen := len(*cStack) - 1
crate := (*cStack)[newLen]
*cStack = (*cStack)[:newLen]
return crate
}
func parseCrateStorage(input []string, stackDesc string) crateStorage {
stackDescVec := strings.Fields(stackDesc)
numStacks, err := strconv.Atoi(stackDescVec[len(stackDescVec)-1])
if err != nil {
panic("Failed to figure out number of stacks")
}
cs := make(crateStorage, numStacks)
for row := len(input) - 1; row >= 0; row-- {
line := input[row]
for stack := 0; stack < numStacks; stack++ {
crate := line[1+stack*4]
if crate != ' ' {
cs[stack].push(crate)
}
}
}
return cs
}
func parseCrateMoves(input []string) []crateMoves {
cm := []crateMoves{}
for _, row := range input {
moves := crateMoves{}
if _, err := fmt.Sscanf(row, "move %d from %d to %d", &moves.cnt, &moves.from, &moves.to); err != nil {
panic("Failed to parse move")
}
cm = append(cm, moves)
}
return cm
}
func parseCrates(input []string) (crateStorage, []crateMoves) {
for i, row := range input {
if row == "" {
return parseCrateStorage(input[:i-1], input[i-1]), parseCrateMoves(input[i+1:])
}
}
panic("Invalid input")
}
func copyCrateStorage(cs crateStorage) crateStorage {
copy := append(crateStorage{}, cs...)
for i := range copy {
copy[i] = append(crateStack{}, copy[i]...)
}
return copy
}
func createMsg(crates crateStorage) string {
msg := []byte{}
for _, crate := range crates {
msg = append(msg, crate.pop())
}
return string(msg)
}
func moveCrates9000(crates crateStorage, moveInstr []crateMoves) string {
for _, moves := range moveInstr {
for cnt := 0; cnt < moves.cnt; cnt++ {
crates[moves.to-1].push(crates[moves.from-1].pop())
}
}
return createMsg(crates)
}
func moveCrates9001(crates crateStorage, moveInstr []crateMoves) string {
stack := crateStack{}
for _, moves := range moveInstr {
for cnt := 0; cnt < moves.cnt; cnt++ {
stack.push(crates[moves.from-1].pop())
}
for len(stack) > 0 {
crates[moves.to-1].push(stack.pop())
}
}
return createMsg(crates)
}
func day5(input []string) {
storage, moves := parseCrates(input)
fmt.Println(moveCrates9000(copyCrateStorage(storage), moves))
fmt.Println(moveCrates9001(storage, moves))
}
func init() {
Solutions[5] = day5
}
HÀlften av koden Àr parsning...
Del 2 löstest pÄ enkla sÀttet, inte det effektivare. LÀgg paketen i ett mellanlager, dÄ blir den omvÀnd ordning i mellanlagret och rÀtt ordning i efterföljande steg -> samma algoritm som i del 1 fungerar Àven dÀr
Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer
Dag: 5
SprÄk: js
Funderade pÄ att skriva en parser för startdatan men det skulle ta lÀngre tid Àn att bara skriva in det i ett par arrayer sÄ jag betade pÄ att jag inte skulle behöva Àndra nÄgot dÀr.
Gjorde samma sak med instruktionerna, ersatte 'move ', ' from ' och ' to ' sÄ jag fick en array i form av [2,4,6] (move 2 from 4 to 6) nÀr jag la in dem.
Sedan var det bara att iterera över instruktionerna.
const startData= {
1: ['N','R','G','P'],
2: ['J','T','B','L','F','G','D','C'],
3: ['M','S','V'],
4: ['L','S','R','C','Z','P'],
5: ['P','S','L','V','C','W','D','Q'],
6: ['C','T','N','W','D','M','S'],
7: ['H','D','G','W','P'],
8: ['Z','L','P','H','S','C','M','V'],
9: ['R','P','F','L','W','G','Z']
};
const instructions = [[2,4,6], etc. ]
instructions.forEach(instruction => {
for(let i = instruction[0]; i>0; i--){
startData[instruction[2]].push(startData[instruction[1]].pop());
}
});
Object.values(startData).forEach(stack => console.log(stack.pop()));
Edit: jag inser nu att jag kunde kört splice + reverse + concat hÀr för att slippa forloopen
Del 2
Ăndrade iterationen till att köra concat/ splice istĂ€llet för push/pop:
instructions.forEach(instruction => {
startData[instruction[2]] = startData[instruction[2]].concat(startData[instruction[1]].splice((-1*instruction[0]),instruction[0]));
});
Att föresprÄka Mac pÄ Swec Àr som att föresprÄka hybridbilar pÄ en raggartrÀff i Mora.
Borde inte din M1 vara överlÀgsen min MBP2017, 15"?
Inte nödvÀndigtvis. Testade pÄ en i7-8559U (Intel NUC, men tror det Àr en CPU Àven Apple anvÀnt i MBP) och den Àr ibland snabbare om man enbart sjÀlva berÀkningen i lÀgen dÀr berÀkningen Àr trivial/vÀldigt enkel.
NÀr nÄgot Àr enkelt och samtidigt inte innehÄller massiv mÀngd parallellism pÄ instruktionsnivÄ slÄr högre frekvens "bredare" design.
I samma problem, mÀter man istÀllet hela flödet, d.v.s. inklusive parsing, Àr M1 vÀsentligt mycket snabbare Àn i7-8559U. Ser samma sak med dagens problem, sjÀlva berÀkningen Àr vÀldigt serialiserad och Àr snabbare pÄ i7-8559U (som klockar 4,5 GHz) medan hela flödet Àr klart snabbare pÄ M1
Sen finns Go-specifika orsaker: i de senaste versionerna har man gjort förÀndringar som pÄverkat prestanda rÀtt ordentligt. Vissa av dessa förÀndringar Àr CPU-arkitekturspecifika dÀr x86_64 fick vissa optimeringar versionen innan de kom till ARM64. Det handlar om upp mot 20 % prestandaökningar!
Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer
Dag: 5
SprÄk: Nim
Lösning: Github
Blev sÄ glad nÀr jag insÄg att man sjÀlvklart kunde representera en stack av lÄdor med datatypen stack xD. Idag var den svÄraste parsingen för i Är hittils. Men gick hyffsat smidigt om Àn kanske inte optimal prestanda.
include prelude, strscans, algorithm
proc crateNumber(indent: int): int =
indent div 4
proc readInput*(input: string): tuple[stack: seq[seq[char]], instructions: seq[tuple[start, to, amount: int]]] =
result.stack = newSeq[seq[char]](9)
for line in input.splitLines:
if '[' in line:
# crate
for i, c in line:
if c == '[':
let crate = crateNumber(i)
result.stack[crate].add line[i+1]
elif line.startsWith("move"):
# move
var instr: tuple[start, to, amount: int]
assert scanf(line, "move $i from $i to $i", instr.amount, instr.start, instr.to)
# zero-index adjust
instr.start -= 1
instr.to -= 1
result.instructions.add instr
# reverse stacks
for i in 0 .. result.stack.high:
result.stack[i].reverse()
proc part1(input: string) =
var (stack, instructions) = readInput(input)
for (start, to, amount) in instructions:
for i in 0 ..< amount:
stack[to].add stack[start].pop()
var answer: seq[char]
for s in stack:
answer.add s[^1]
echo "Part 1: ", answer.join("")
proc part2(input: string) =
var (stack, instructions) = readInput(input)
for (start, to, amount) in instructions:
let movedCrates = stack[start][^amount .. ^1]
stack[start].setLen(stack[start].len - amount)
stack[to].add movedCrates
var answer: seq[char]
for s in stack:
answer.add s[^1]
echo "Part 2: ", answer.join("")
when isMainModule:
let input = readFile("input.txt")
part1(input)
part2(input)
Dag: 5
SprÄk: C#
SpÀnnande problem. Tog en stund att komma pÄ en "bra" strategi för parsing
public sealed class SupplyStacks : Puzzle<string>
{
public override string A(string data)
{
var sections = data
.Split("\r\n\r\n");
var stacks = ExtractStacks(sections);
foreach (var line in sections[1].Split("\r\n"))
{
var instructions = line.Split(" ");
var amount = int.Parse(instructions[1]);
for (int i = 0; i < amount; i++)
{
stacks[int.Parse(instructions[5]) - 1].Push(stacks[int.Parse(instructions[3]) - 1].Pop());
}
}
return PeekStacks(stacks);
}
public override string B(string data)
{
var sections = data
.Split("\r\n\r\n");
var stacks = ExtractStacks(sections);
foreach (var line in sections[1].Split("\r\n"))
{
var instructions = line.Split(" ");
var amount = int.Parse(instructions[1]);
Stack<char> crates = new Stack<char>();
for (int i = 0; i < amount; i++)
{
crates.Push(stacks[int.Parse(instructions[3]) - 1].Pop());
}
while (crates.Count != 0)
{
stacks[int.Parse(instructions[5]) - 1].Push(crates.Pop());
}
}
return PeekStacks(stacks);
}
private static List<Stack<char>> ExtractStacks(IReadOnlyList<string> sections)
{
var stackSection = sections[0].Split("\r\n");
List<Stack<char>> stacks = new List<Stack<char>>();
for (int i = 0; i <= stackSection[^1].Length / 4; i++)
{
stacks.Add(new Stack<char>());
}
for (int i = stackSection.Length - 2; i >= 0; i--)
{
var chunks = stackSection[i].Chunk(4).Select(c => new string(c[..3])).ToArray();
for (int j = 0; j < chunks.Length; j++)
{
if (chunks[j] != " ")
{
stacks[j].Push(chunks[j][1]);
}
}
}
return stacks;
}
private static string PeekStacks(IEnumerable<Stack<char>> stacks)
{
return string.Join(null, stacks
.Select(s => s.Peek()));
}
}
Dag: 5
SprÄk: Python3
Blev ingen supersnygg lösning men den funkar.
MÀrktes direkt att det var lite svÄrare idag. Satan vad man klÀttrade i rank.
with open('Day5/data.txt') as file:
data = file.readlines()
stack = data[0:8]
moves = data[10:]
stack_list = [""] * len(max(stack, key=len))
for line in stack:
line_clean = line.strip()
for n, letter in enumerate(line_clean):
if 'A' <= letter <= 'Z':
stack_list[n] = stack_list[n] + letter
while '' in stack_list:
stack_list.remove('')
stack_list2 = stack_list.copy() # For second half of puzzle
moves_list = []
for text_moves in moves:
moves_list.append([int(s) for s in text_moves.split() if s.isdigit()])
def rearrange_crate(stack_remove, stack_add, n_moves):
for move in range(n_moves):
stack_add = stack_remove[0] + stack_add
stack_remove = stack_remove[1:]
return stack_remove, stack_add
def print_answer(stacks):
answer = ''
for stack in stacks:
answer = answer + stack[0]
print(answer)
for move in moves_list:
new_stacks = rearrange_crate(stack_list[move[1] - 1], stack_list[move[2] - 1], move[0])
stack_list[move[1] - 1] = new_stacks[0]
stack_list[move[2] - 1] = new_stacks[1]
print_answer(stack_list) # Print first answer
def rearrange_crate_9001(stack_remove, stack_add, n_moves):
stack_add = stack_remove[0:n_moves] + stack_add
stack_remove = stack_remove[n_moves:]
return stack_remove, stack_add
for move in moves_list:
new_stacks = rearrange_crate_9001(stack_list2[move[1] - 1], stack_list2[move[2] - 1], move[0])
stack_list2[move[1] - 1] = new_stacks[0]
stack_list2[move[2] - 1] = new_stacks[1]
print_answer(stack_list2) # Print second answer
Dag: 5
SprÄk: Python
import re
def read_creates(f):
crates = ["" for _ in range(9)]
while l := f.readline().strip('\n'):
crates = [crates[i] + c for i, c in enumerate(l[1::4])]
return [""] + [c[:-1][::-1].strip() for c in crates]
def read_moves(f):
return [map(int, re.findall(r'\d+', l)) for l in f.readlines()]
def do_moves(crates, moves, reverse):
for n, f, t in moves:
crates[t] = crates[t] + crates[f][-n:][::reverse]
crates[f] = crates[f][:-n]
return crates
def day05(reverse):
with open("input05", "r") as f:
crates = do_moves(read_creates(f), read_moves(f), reverse)
return("".join([c[-1] for c in crates[1:]]))
print([day05(r) for r in [-1, 1]])
Dag: 5
SprÄk: F# som fÄr en att grÄta
Inte skitsnyggt, men det fungerar
open System
open System.IO
open System.Text.RegularExpressions
type instruction = {howMany: int; fromWhere: int; toWhere: int;}
let parse =
let data = File.ReadAllLines "input.txt"
let folder (m:Map<int, char list>) c = m.Add (((c |> Seq.head |> int)-int('0')), c |> Seq.tail |> Seq.filter (fun c -> c <> ' ') |> Seq.rev |> Seq.toList)
let map = data |> Seq.takeWhile (fun c -> c.Trim() <> "") |> Seq.transpose |> Seq.map Seq.rev
|> Seq.filter (Seq.head >> (fun c -> c <> ' '))
|> Seq.fold folder Map.empty
let parseInstruction row =
let matches = Regex.Match(row, "move ([0-9]+) from ([0-9]+) to ([0-9])+")
{howMany = matches.Groups[1].Value |> int; fromWhere = matches.Groups[2].Value |> int; toWhere = matches.Groups[3].Value |> int }
let instructions = data |> Seq.skipWhile (fun c-> c.Trim() <> "") |> Seq.skip 1 |> Seq.map parseInstruction
(map, instructions)
let move listAction (map:Map<int, char list>) instruction =
let toStack = map |> Map.find instruction.toWhere
let fromStack = map |> Map.find instruction.fromWhere
let taken, rest = fromStack |> List.splitAt instruction.howMany
map |> Map.add instruction.fromWhere rest |> Map.add instruction.toWhere ((taken |> listAction) @ toStack)
let map, instructions = parse
let task task' = instructions |> Seq.fold (move task') map |> Map.map (fun _ -> List.head) |> Map.toList |> List.sortBy fst |> List.map snd |> List.toArray |> String;
printfn "Task 1: %s" (task List.rev)
printfn "Task 2: %s" (task (List.skip 0))
Jag Àr en optimist; det Àr aldrig sÄ dÄligt sÄ att det inte kan bli sÀmre.
Dag: 5
SprÄk: Java
Lösning: ...
uph.
public class DayFive {
public static void main(String[] args) {
List<String> crates = new ArrayList<>();
List<String> instructions = new ArrayList<>();
try {
File file = new File("C:\\AoC 22\\inputDay5.txt");
FileReader filereader = new FileReader(file);
BufferedReader bufferedreader = new BufferedReader(filereader);
String line;
while((line = bufferedreader.readLine()) != null) {
if(line.contains("move"))
instructions.add(line);
else
crates.add(line);
}
filereader.close();
} catch(IOException e) {
e.printStackTrace();
}
List<Stack<Character>> stackList = new ArrayList<>();
Stack<Character> one = new Stack<>();
Stack<Character> two = new Stack<>();
Stack<Character> three = new Stack<>();
Stack<Character> four = new Stack<>();
Stack<Character> five = new Stack<>();
Stack<Character> six = new Stack<>();
Stack<Character> seven = new Stack<>();
Stack<Character> eight = new Stack<>();
Stack<Character> nine = new Stack<>();
stackList.add(one);
stackList.add(two);
stackList.add(three);
stackList.add(four);
stackList.add(five);
stackList.add(six);
stackList.add(seven);
stackList.add(eight);
stackList.add(nine);
for(int i = crates.size()-1; i >= 0; i--) {
String temp = crates.get(i);
for(int j = 0; j <= temp.length()-1; j++) {
if(Character.isAlphabetic(temp.charAt(j)) && !Character.isDigit(temp.charAt(j))) {
if(j == 1)
one.push(temp.charAt(j));
else if(j == 5)
two.push(temp.charAt(j));
else if(j == 9)
three.push(temp.charAt(j));
else if(j == 13)
four.push(temp.charAt(j));
else if(j == 17)
five.push(temp.charAt(j));
else if(j == 21)
six.push(temp.charAt(j));
else if(j == 25)
seven.push(temp.charAt(j));
else if(j == 29)
eight.push(temp.charAt(j));
else if(j == 33)
nine.push(temp.charAt(j));
}
}
}
List<String> instructionsclean = new ArrayList<>();
for(int i = 0; i < instructions.size(); i++) {
String temp = instructions.get(i);
temp = temp.replace("move ", "");
temp = temp.replace("from ", "");
temp = temp.replace("to ", "");
instructionsclean.add(temp);
}
for(int i = 0; i < instructionsclean.size(); i++) {
String temp = instructionsclean.get(i);
int move = Integer.parseInt(temp.substring(0, temp.indexOf(' ')));
int from = Integer.parseInt(temp.substring(temp.indexOf(' ')+1, temp.indexOf(' ')+2));
int to = Integer.parseInt(temp.substring(temp.indexOf(' ')+3, temp.length()));
for(int m = 1; m <= move; m++) {
char chara = stackList.get(from-1).pop();
stackList.get(to-1).push(chara);
}
}
System.out.println("part one: " + stackList.get(0).peek() + " " + stackList.get(1).peek() + " " + stackList.get(2).peek()
+ " " + stackList.get(3).peek() + " " + stackList.get(4).peek() + " " + stackList.get(5).peek()
+ " " + stackList.get(6).peek() + " " + stackList.get(7).peek() + " " + stackList.get(8).peek());
/*
* resetting stacks
*/
stackList.get(0).removeAllElements();
stackList.get(1).removeAllElements();
stackList.get(2).removeAllElements();
stackList.get(3).removeAllElements();
stackList.get(4).removeAllElements();
stackList.get(5).removeAllElements();
stackList.get(6).removeAllElements();
stackList.get(7).removeAllElements();
stackList.get(8).removeAllElements();
for(int i = crates.size()-1; i >= 0; i--) {
String temp = crates.get(i);
for(int j = 0; j <= temp.length()-1; j++) {
if(Character.isAlphabetic(temp.charAt(j)) && !Character.isDigit(temp.charAt(j))) {
if(j == 1)
one.push(temp.charAt(j));
else if(j == 5)
two.push(temp.charAt(j));
else if(j == 9)
three.push(temp.charAt(j));
else if(j == 13)
four.push(temp.charAt(j));
else if(j == 17)
five.push(temp.charAt(j));
else if(j == 21)
six.push(temp.charAt(j));
else if(j == 25)
seven.push(temp.charAt(j));
else if(j == 29)
eight.push(temp.charAt(j));
else if(j == 33)
nine.push(temp.charAt(j));
}
}
}
for(int i = 0; i < instructionsclean.size(); i++) {
String temp = instructionsclean.get(i);
int move = Integer.parseInt(temp.substring(0, temp.indexOf(' ')));
int from = Integer.parseInt(temp.substring(temp.indexOf(' ')+1, temp.indexOf(' ')+2));
int to = Integer.parseInt(temp.substring(temp.indexOf(' ')+3, temp.length()));
List<Character> tempList = new ArrayList<>();
for(int m = 1; m <= move; m++) {
char chara = stackList.get(from-1).remove(stackList.get(from-1).size()-1);
tempList.add(chara);
}
for(int k = tempList.size()-1; k >= 0; k--)
stackList.get(to-1).push(tempList.get(k));
tempList.clear();
}
System.out.println("part two: " + stackList.get(0).peek() + " " + stackList.get(1).peek() + " " + stackList.get(2).peek()
+ " " + stackList.get(3).peek() + " " + stackList.get(4).peek() + " " + stackList.get(5).peek()
+ " " + stackList.get(6).peek() + " " + stackList.get(7).peek() + " " + stackList.get(8).peek());
}
Dag 5
SprÄk C#
Nu börjar man kÀnna igen den, textparsningsmisÀren. NÄja, jag Àr vÀl ÀndÄ hyfsat nöjd med hur det blev till slut (iaf nu efter att jag gÄtt över den igen nu ikvÀll)
Kod:
using var sr = new StreamReader("input.txt");
bool is_orders = false;
Stack<string> the_stack = new();
List<Stack<string>> stacks_pt1 = new();
List<Stack<string>> stacks_pt2 = new();
while (!sr.EndOfStream)
{
var line = sr.ReadLine()!;
if (string.IsNullOrEmpty(line))
{
is_orders = true;
int num = int.Parse(the_stack.Pop()[^2..]);
for (int i = 0; i < num; i++)
{
stacks_pt1.Add(new());
stacks_pt2.Add(new());
}
while (the_stack.Any())
{
stackify(the_stack.Pop());
}
continue;
}
if (!is_orders)
{
the_stack.Push(line);
}
else
{
operate_crane(line);
}
}
Console.Write("Part 1: ");
printresult(stacks_pt1);
Console.Write("Part 2: ");
printresult(stacks_pt2);
void operate_crane(string order)
{
var splat = order.Split(' ');
int crates = int.Parse(splat.ElementAt(1));
int from = int.Parse(splat.ElementAt(3)) -1;
int to = int.Parse(splat.ElementAt(5)) -1;
Stack<string> tempstack = new();
for (int i = 0; i < crates; i++)
{
stacks_pt1.ElementAt(to).Push(stacks_pt1.ElementAt(from).Pop());
tempstack.Push(stacks_pt2.ElementAt(from).Pop());
}
while (tempstack.Any())
{
stacks_pt2.ElementAt(to).Push(tempstack.Pop());
}
}
void stackify(string line)
{
int last_stack_line_position = line.Length;
int linepos = 1;
int stacklistelement = 0;
while (linepos <= last_stack_line_position)
{
if (line[linepos] != ' ')
{
stacks_pt1.ElementAt(stacklistelement).Push($"{line[linepos]}");
stacks_pt2.ElementAt(stacklistelement).Push($"{line[linepos]}");
}
linepos += 4;
stacklistelement++;
}
}
void printresult(List<Stack<string>> stacks)
{
foreach (var row in stacks)
{
Console.Write(row.Peek());
}
Console.WriteLine();
}
The power of GNU compiles you!
"Often statistics are used as a drunken man uses lampposts -- for support rather than illumination."
Inte nödvÀndigtvis. Testade pÄ en i7-8559U (Intel NUC, men tror det Àr en CPU Àven Apple anvÀnt i MBP) och den Àr ibland snabbare om man enbart sjÀlva berÀkningen i lÀgen dÀr berÀkningen Àr trivial/vÀldigt enkel.
NÀr nÄgot Àr enkelt och samtidigt inte innehÄller massiv mÀngd parallellism pÄ instruktionsnivÄ slÄr högre frekvens "bredare" design.
I samma problem, mÀter man istÀllet hela flödet, d.v.s. inklusive parsing, Àr M1 vÀsentligt mycket snabbare Àn i7-8559U. Ser samma sak med dagens problem, sjÀlva berÀkningen Àr vÀldigt serialiserad och Àr snabbare pÄ i7-8559U (som klockar 4,5 GHz) medan hela flödet Àr klart snabbare pÄ M1
Sen finns Go-specifika orsaker: i de senaste versionerna har man gjort förÀndringar som pÄverkat prestanda rÀtt ordentligt. Vissa av dessa förÀndringar Àr CPU-arkitekturspecifika dÀr x86_64 fick vissa optimeringar versionen innan de kom till ARM64. Det handlar om upp mot 20 % prestandaökningar!
Tack för ett informativt svar!
Dag: 5
SprÄk: Go
Parsningen tog en stund att knÀcka idag. Och sÄ rÄkade jag lösa del 2 först, sÄ jag kÀnde igen svaren nÀr jag kom dit :p. Benchtestet nedan innehÄller en kopiering av crates "objektet".
go test -bench=. ./...
goos: darwin
goarch: amd64
pkg: aoc2022/05/a
cpu: Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz
BenchmarkPartOne-8 153040 6949 ns/op
BenchmarkPartTwo-8 218338 5360 ns/op
PASS
ok aoc2022/05/a 2.607s
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
type Instruction struct {
Count int
From int
To int
}
func getResult(crateStacks [][]rune) string {
result := ""
for _, stack := range crateStacks {
result += string(stack[len(stack)-1:])
}
return result
}
func reverse(r []rune) {
for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
}
func moveCrates(crateStacks [][]rune, instructions []Instruction, preservePickOneByOneOrder bool) {
for _, inst := range instructions {
fromStack := crateStacks[inst.From]
stackIndex := len(fromStack) - inst.Count
lastCrates := fromStack[stackIndex:] // get last
crateStacks[inst.From] = fromStack[:stackIndex] // remove last
if preservePickOneByOneOrder {
reverse(lastCrates)
}
crateStacks[inst.To] = append(crateStacks[inst.To], lastCrates...)
}
}
func getPartOne(crateStacks [][]rune, instructions []Instruction) string {
moveCrates(crateStacks, instructions, true)
result := getResult(crateStacks)
return result
}
func getPartTwo(crateStacks [][]rune, instructions []Instruction) string {
moveCrates(crateStacks, instructions, false)
result := getResult(crateStacks)
return result
}
func getRows(filename string) ([][]rune, []Instruction) {
file, err := os.Open(filename)
if err != nil {
panic(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
crateStacks := make([][]rune, 0)
instructions := make([]Instruction, 0)
for scanner.Scan() {
row := scanner.Text()
if strings.Contains(row, "[") {
for i := 1; i < len(row); i += 4 {
j := (i - 1) / 4
if j+1 > len(crateStacks) {
crateStacks = append(crateStacks, make([]rune, 0))
}
if string(row[i]) != " " {
crateStacks[j] = append(crateStacks[j], int32(row[i]))
}
}
} else if strings.Contains(row, "move") {
var inst Instruction
fmt.Sscanf(row, "move %d from %d to %d",
&inst.Count, &inst.From, &inst.To)
inst.From -= 1
inst.To -= 1
instructions = append(instructions, inst)
}
}
// Reverse the crateStack
for _, crateStack := range crateStacks {
reverse(crateStack)
}
return crateStacks, instructions
}
func main() {
fmt.Println("Part one:", getPartOne(getRows("../input.txt")))
fmt.Println("Part two:", getPartTwo(getRows("../input.txt")))
}
Dag 5 i Kotlin, nu börjar det bli fult pÄ ögat.
data class Crate(val crateMarking: Char)
data class CrateStack(val stack: ArrayDeque<Crate>)
data class MoveInstruction(val numberToMove: Int, val target: Int, val destination: Int)
fun run() {
val input = File("src/input/day5.txt").readText()
val inputParts = input.split("\r\n\r\n")
val crates = inputParts[0]
val instructions = inputParts[1]
val rowsFromBottom = crates.split("\n").reversed()
val numberOfStacks = rowsFromBottom.first().trim().last().digitToInt()
val part1Lambda = {moves: Int, targetStack: CrateStack, destinationStack: CrateStack ->
for (i in 1..moves) {
destinationStack.stack.addFirst(targetStack.stack.removeFirst())
}
}
val part2Lambda = {moves: Int, targetStack: CrateStack, destinationStack: CrateStack ->
val tempCrateStack = ArrayDeque<Crate>()
for (i in 1..moves) {
val topCrate = targetStack.stack.removeFirst()
tempCrateStack.add(topCrate)
}
repeat(tempCrateStack.size) { destinationStack.stack.addFirst(tempCrateStack.removeLast()) }
}
println(solver(part1Lambda, instructions, getCrates(rowsFromBottom, numberOfStacks)))
println(solver(part2Lambda, instructions, getCrates(rowsFromBottom, numberOfStacks)))
}
private fun getCrates(rowsFromBottom: List<String>, numberOfStacks: Int): List<CrateStack> {
val stacks = IntRange(1, numberOfStacks).map { CrateStack(ArrayDeque()) }
rowsFromBottom.drop(1).forEach { row ->
for ((currentStack, i) in (1..row.length step 4).withIndex()) {
val crateMarking = row[i]
if (crateMarking.isLetter()) {
val crate = Crate(crateMarking)
stacks[currentStack].stack.addFirst(crate)
}
}
}
return stacks
}
private fun solver(lambda: (Int,CrateStack, CrateStack) -> Unit, moveInstructions: String, stacks:List<CrateStack>): String {
buildMoveCrateInstruction(moveInstructions).forEach { instruction ->
val targetStack = stacks[instruction.target - 1]
val destinationStack = stacks[instruction.destination - 1]
lambda(instruction.numberToMove, targetStack, destinationStack)
}
return stacks.map { it.stack.first().crateMarking }.toString()
}
private fun buildMoveCrateInstruction(moveInstructions: String): List<MoveInstruction> {
val instructionParts = moveInstructions.split("\r\n").map { it.split(" ") }
return instructionParts.map { MoveInstruction(it[1].toInt(), it[3].toInt(), it.last().toInt()) }
}
Dag: 5
SprÄk: Kotlin
Blev inte sÄ snyggt, och hade svÄrt att göra denna uppgift utan att mutera en massa, men det fungerar.
// Parse the instruction strings and create instruction objects
val instructionList = instructions.lines()
.map { Regex("([0-9]+)").findAll(it).map { it.value }.toList() }
.map { Instruction(it[0].toInt(), it[1].toInt(), it[2].toInt()) }
println("Part 1: ${part1Day5(stack, instructionList)} Part 2:${part2Day5(stack, instructionList)}")
}
data class Instruction(val number: Int, val from: Int, val to: Int)
// Create a list of "stack" lists corresponding to the given initial crate positions.
fun crateSetup(stack: String) = stack.lines().reversed().flatMap { it.withIndex().toList() }
.groupBy(keySelector = { it.index }, valueTransform = {it.value})
.map { it.value.filter { it.isLetter() } }.filter { it.isNotEmpty() }.map { it.toMutableList() }
// Order a copy of the crate stacks, mutate according to the instructions. Return the top element char in each stack
fun part1Day5(stack: String, instructionList: List<Instruction>): String {
val stackList = crateSetup(stack)
for (instruction in instructionList) {
for (i in 0 until instruction.number) {
stackList[instruction.to - 1].add(stackList[instruction.from - 1].removeLast())
}
}
return stackList.map { it.last() }.joinToString("")
}
fun part2Day5(stack: String, instructionList: List<Instruction>): String {
val stackList = crateSetup(stack)
for (instruction in instructionList) {
val position = stackList[instruction.from - 1].size - instruction.number
for (i in 0 until instruction.number) {
stackList[instruction.to - 1].add(stackList[instruction.from - 1].removeAt(position))
}
}
return stackList.map { it.last() }.joinToString("")
}
i5-7600k . GTX 1080 . 16 GB
Dag: 5
SprÄk: Scala
SÄg att jag skrev fel dag i förra inlÀgget. Det hÀr Àr dag 5 pÄ riktigt.
Dagens uppgift kÀndes lite trÄkig sÄ nöjde mig med att bara plocka fram rÀtt svar utan att snygga till koden.
val input = Using.resource(Source.fromFile("""5.txt"""))(_.getLines().toVector)
val (crates, moves) = input.span(_ != "")
val crates2 = crates.map(str => (1 to str.length by 4).map(str)).transpose.map(_.dropWhile(_ == ' ').init)
moves.foldLeft(crates2) { (state, move) =>
move match
case s"move $amount from $from to $to" =>
val (fst, snd) = state(from.toInt - 1).splitAt(amount.toInt)
state.updated(from.toInt - 1, snd).updated(to.toInt - 1, fst.reverse ++ state(to.toInt - 1))
case _ => state
}.map(_.head).mkString
moves.foldLeft(crates2) { (state, move) =>
move match
case s"move $amount from $from to $to" =>
val (fst, snd) = state(from.toInt - 1).splitAt(amount.toInt)
state.updated(from.toInt - 1, snd).updated(to.toInt - 1, fst ++ state(to.toInt - 1))
case _ => state
}.map(_.head).mkString
Skiljer bara en .reverse mellan del1 och del2.
Dag: 5
SprÄk: Haskell
Inte sÄ nöjd idag, det hÀr Àr kanske pÄ grÀnsen till vad jag klarar av.
Idag blev parsningen Ànnu fulare Àn igÄr. Usch, kolla funktionen readMoves.
-- The program expects the input on stdin, ie
-- $ ./solve < input
import Data.Char (isDigit, isUpper)
main = interact solve
solve :: String -> String
solve input = "Problem 1: " ++ show (map head finalCratesPt1) ++ "\n"
++ "Problem 2: " ++ show (map head finalCratesPt2) ++ "\n"
where finalCratesPt1 = foldr doMovePt1 crates moves
finalCratesPt2 = foldr doMovePt2 crates moves
crates = filter (not.null) (map (filter isUpper) (transpose cratesInput))
moves = reverse (map readMove (filter (not.null) movesInput))
(cratesInput, movesInput) = break null (lines input)
-- Some types for readability.
data Move = Move {num::Int, from::Int, to::Int} deriving (Show)
type Crates = [String]
type Stack = String
transpose :: [[a]] -> [[a]]
transpose ([]:_) = []
transpose x = (map head x) : transpose (map tail x)
-- Parse the strings from the problem input.
readMove :: String -> Move
readMove s = Move a b c
where a = read (takeWhile isDigit (dropWhile (not.isDigit) s))
b = read (takeWhile isDigit (dropWhile (not.isDigit) (dropWhile isDigit (dropWhile (not.isDigit) s))))
c = read (takeWhile isDigit (dropWhile (not.isDigit) (dropWhile isDigit (dropWhile (not.isDigit) (dropWhile isDigit (dropWhile (not.isDigit) s))))))
-- Remove a number of crates from a specific target stack.
popStack :: Move -> Crates -> (Crates, Stack)
popStack move crates = (before ++ [remaining] ++ after, removed)
where (before, target:after) = splitAt ((from move)-1) crates
(removed, remaining) = splitAt (num move) target
-- Place a number of crates on a specific target stack.
pushStack :: Move -> Stack -> Crates -> Crates
pushStack move moved crates = before ++ [moved ++ target] ++ after
where (before, target:after) = splitAt ((to move)-1) crates
-- Perform a move while reversing the crates, for part 1.
doMovePt1 :: Move -> Crates -> Crates
doMovePt1 move crates = pushStack move (reverse moved) crates_
where (crates_, moved) = popStack move crates
-- Perform a move, without reversing the crates, for part 2.
doMovePt2 :: Move -> Crates -> Crates
doMovePt2 move crates = pushStack move moved crates_
where (crates_, moved) = popStack move crates
(Jag anvÀnder highlight som finns i apt för syntaxfÀrgning.)
Dag: 5
SprÄk: VB.Net
edit: Snyggade till koden lite
Imports System.IO
Module Program
Sub Main(args As String())
Dim input = File.ReadAllLines("input.txt")
Dim stacks = resetStacks(input)
Dim instructionStart = Array.FindIndex(input, Function(line) line.Contains("move"))
For i = instructionStart To input.Length - 1 Step 1
Dim instruction = input(i).Split(" ")
For j = 1 To Integer.Parse(instruction(1)) Step 1
stacks(Integer.Parse(instruction(5)) - 1).Push(stacks(Integer.Parse(instruction(3)) - 1).Pop())
Next
Next
Dim part1 As String = ""
For Each stack In stacks
part1 = part1 & stack.Peek
Next
stacks = resetStacks(input)
Dim crane As New Stack(Of Char)
For i = instructionStart To input.Length - 1 Step 1
Dim instruction = input(i).Split(" ")
For j = 1 To Integer.Parse(instruction(1)) Step 1
crane.Push(stacks(Integer.Parse(instruction(3)) - 1).Pop())
Next
For j = 1 To Integer.Parse(instruction(1)) Step 1
stacks(Integer.Parse(instruction(5)) - 1).Push(crane.Pop())
Next
Next
Dim part2 As String = ""
For Each stack In stacks
part2 = part2 & stack.Peek
Next
Console.WriteLine(part1)
Console.WriteLine(part2)
End Sub
Function resetStacks(input As String()) As List(Of Stack(Of Char))
Dim stacks As New List(Of Stack(Of Char))
Dim stacksEnd = Array.FindIndex(input, Function(line) (Not line.Contains("[")))
For i = 0 To ((input(0).Length - 3) / 4) Step 1
stacks.Add(New Stack(Of Char))
Next
For i = stacksEnd - 1 To 0 Step -1
If Not String.IsNullOrWhiteSpace(input(i)(1)) Then
stacks(0).Push(input(i)(1))
End If
For j = 1 To stacks.Count - 1 Step 1
If Not String.IsNullOrWhiteSpace(input(i)(1 + (j * 4))) Then
stacks(j).Push(input(i)(1 + (j * 4)))
End If
Next
Next
Return stacks
End Function
End Module
Dag: 5
SprÄk: Go
Lösning:
package main
import (
"fmt"
"os"
"strconv"
"strings"
)
func getMoves(input string) (int, []string) {
var crateRows int
//Count on which row there's a double linebreak
for i, ch := range input {
if ch == '\n' && input[i+1] != '\n' {
crateRows++
}
if ch == '\n' && input[i+1] == '\n' {
break
}
}
//Return number of rows and the moves
moves := strings.Split(input, "\n")[crateRows+2:]
return crateRows, moves
}
// Function to get the letters from each "crate"
func splitToStacks(input string, crateRows int) [][]string {
rows := strings.Split(input, "\n")[0:crateRows]
crateRow := strings.Split(input, "\n")[crateRows]
numCrates, _ := strconv.Atoi(string(crateRow[len(crateRow)-2]))
stacks := make([][]string, numCrates+1)
for i := len(rows) - 1; i >= 0; i-- {
k := 1
for j := 1; j < len(rows[0])-1; j += 4 {
if string(rows[i][j]) != " " {
stacks[k] = append(stacks[k], string(rows[i][j]))
}
k++
}
}
return stacks
}
func splitMoves(moves []string) [][]int {
toret := make([][]int, len(moves))
for i := 0; i < len(moves); i++ {
//Split each move into numbers
move := strings.Split(moves[i], " ")
tempNum, _ := strconv.Atoi(move[1])
tempFrom, _ := strconv.Atoi(move[3])
tempTo, _ := strconv.Atoi(move[5])
//Save the numbers to an array
toret[i] = append(toret[i], tempNum)
toret[i] = append(toret[i], tempFrom)
toret[i] = append(toret[i], tempTo)
}
return toret
}
func MakeMoves1(stacks [][]string, moves [][]int) [][]string {
for i := 0; i < len(moves); i++ {
num := moves[i][0]
from := moves[i][1]
to := moves[i][2]
//Move the correct number of letters from the "from" stack to the "to" stack
for j := 0; j < num; j++ {
stacks[to] = append(stacks[to], stacks[from][len(stacks[from])-1])
stacks[from] = stacks[from][:len(stacks[from])-1]
}
}
return stacks
}
func MakeMoves2(stacks [][]string, moves [][]int) [][]string {
for i := 0; i < len(moves); i++ {
num := moves[i][0]
from := moves[i][1]
to := moves[i][2]
//Move letters from the "from" stack to the "to" stack in batches on "num"
stacks[to] = append(stacks[to], stacks[from][len(stacks[from])-num:]...)
stacks[from] = stacks[from][:len(stacks[from])-num]
}
return stacks
}
func printLast(stacks [][]string) {
for i := 1; i < len(stacks); i++ {
fmt.Print(stacks[i][len(stacks[i])-1])
}
}
func main() {
input, _ := os.ReadFile("input.txt")
inputString := string(input)
//Find separator between crates and moves
crateRows, tempmoves := getMoves(inputString)
//Get the crate letters into an array per collumn
stacks := splitToStacks(inputString, crateRows)
//Split moverows into pure numbers
moves := splitMoves(tempmoves)
//Create stack for first method
stacks1 := MakeMoves1(stacks, moves)
//Need to recreate stacks because MakeMoves1 changes the original
stacks = splitToStacks(inputString, crateRows)
//Create stack for second method
stacks2 := MakeMoves2(stacks, moves)
//Print last element of each stack
printLast(stacks1)
fmt.Println()
printLast(stacks2)
}
Citera sÄ hittar jag tillbaks och kan ge svar.
Dag 5
SprÄk: Node (js)
Tycker det Àr lite halvtradigt nÀr dom meckar till parsingen, det Àr inte riktigt dÀr jag tycker om att lÀgga tid pÄ dessa.
import { data, testData } from "../input/day5.js";
function getData(rawData) {
let instructions;
let input;
[input, instructions] = data.split('\n\n');
input = input.split('\n');
const matris = [];
for (const line of input) {
if (line.substring(0, 3) === ' 1 ') {
break;
}
for (let i = 1; i <= line.length; i+=4) {
if (line[i] === ' ') continue;
else {
const n = Math.round(i / 4);
while (matris.length <= n) {
matris.push([]);
}
matris[n].push(line[i])
}
}
}
for (let i = 0; i < matris.length; i++) {
matris[i] = matris[i].reverse();
}
instructions = instructions
.split('\n').map(row => row
.split(' ')
.filter(n => n
.match(/[0-9]+/g))
.map(n => parseInt(n)));
return { matris, instructions }
}
function getVisibleCrates(matris) {
let str = '';
for (let i = 0; i < matris.length; i++) {
str += matris[i].at(-1);
}
return str;
}
const solutionA = () => {
const { matris, instructions } = getData(data);
for (const instruction of instructions) {
const [amount, from, to] = instruction;
for (let i = 0; i < amount; i++) {
matris[to - 1].push(...matris[from - 1].pop());
}
}
console.log(getVisibleCrates(matris));
}
const solutionB = () => {
const { matris, instructions } = getData(data);
for (const instruction of instructions) {
const [amount, from, to] = instruction;
matris[to - 1].push(...matris[from - 1].splice(-amount));
}
console.log(getVisibleCrates(matris));
}
export { solutionA, solutionB };
Dag: 5
SprÄk: C++
Blev ingen vidare tjusig lösning idag, parsningen stÀllde till det lite. Hade ocksÄ en size_t som datatyp i en for loop som subtraherade ner till 0:
for (size_t j = rowIndex - 1; j >= 0; j--)
vilket resulterar i en underflow vilket var lite störigt att felsöka innan jag insÄg mitt misstag
#include "../AoCHelper/AoCHelper.h"
#include <vector>
#include <stack>
void puzzle_one(std::vector<std::string> &input)
{
bool parseStacks{true};
std::vector<std::stack<char>> stacks{};
for (size_t i = 0; i <= 9; i++)
{
stacks.push_back(std::stack<char>()); // 0 will be unused
}
for (size_t rowIndex = 0; rowIndex < input.size(); rowIndex++)
{
std::string row = input[rowIndex];
if (parseStacks)
{
if (row.find(" 1 2 3 ") == std::string::npos)
{
continue;
}
parseStacks = false;
for (size_t i = 1; (i + 1) < row.size(); i += 4)
{
for (int j = rowIndex - 1; j >= 0; j--)
{
if (input[j][i] != ' ')
{
stacks[(i / 4) + 1].push(input[j][i]);
}
}
}
}
else
{
if (row.find("move") == std::string::npos)
{
continue;
}
auto splitRow = (myLib::split(row, ' '));
int amount = std::stoi(splitRow[1]);
int from = std::stoi(splitRow[3]);
int to = std::stoi(splitRow[5]);
for (int i = 0; i < amount; i++)
{
stacks[to].push(stacks[from].top());
stacks[from].pop();
}
}
}
std::string answer{};
for (size_t i = 1; i <= 9; i++)
{
if (!stacks[i].empty())
{
answer.push_back(stacks[i].top());
}
}
std::cout << "Puzzle one: " << answer << std::endl;
}
void puzzle_two(std::vector<std::string> &input)
{
bool parseStacks{true};
std::vector<std::stack<char>> stacks{};
for (size_t i = 0; i <= 9; i++)
{
stacks.push_back(std::stack<char>()); // 0 will be unused
}
for (size_t rowIndex = 0; rowIndex < input.size(); rowIndex++)
{
std::string row = input[rowIndex];
if (parseStacks)
{
if (row.find(" 1 2 3 ") == std::string::npos)
{
continue;
}
parseStacks = false;
for (size_t i = 1; (i + 1) < row.size(); i += 4)
{
for (int j = rowIndex - 1; j >= 0; j--)
{
if (input[j][i] != ' ')
{
stacks[(i / 4) + 1].push(input[j][i]);
}
}
}
}
else
{
if (row.find("move") == std::string::npos)
{
continue;
}
const auto splitRow = (myLib::split(row, ' '));
const int amount = std::stoi(splitRow[1]);
const int from = std::stoi(splitRow[3]);
const int to = std::stoi(splitRow[5]);
std::stack<char> tempStack{};
for (int i = 0; i < amount; i++)
{
tempStack.push(stacks[from].top());
stacks[from].pop();
}
for (int i = 0; i < amount; i++)
{
stacks[to].push(tempStack.top());
tempStack.pop();
}
}
}
std::string answer{};
for (size_t i = 1; i <= 9; i++)
{
if (!stacks[i].empty())
{
answer.push_back(stacks[i].top());
}
}
std::cout << "Puzzle two: " << answer << std::endl;
}
int main()
{
std::vector<std::string> exampleInput{
" [D] ",
"[N] [C] ",
"[Z] [M] [P]",
" 1 2 3 ",
"",
"move 1 from 2 to 1",
"move 3 from 1 to 3",
"move 2 from 2 to 1",
"move 1 from 1 to 2"
};
AoCHelper a1{"2022", "5"};
std::vector<std::string> result = a1.get_input();
puzzle_one(result);
puzzle_two(result);
}
Dag: 5
SprÄk: C#
using AOC.Helpers.Extensions;
using System.Text.RegularExpressions;
namespace AOC2022.Puzzles;
internal partial class Puzzle5 : Puzzle<string>
{
[GeneratedRegex(@move (\d+) from (\d+) to (\d+))] private static partial Regex InstructionRegex();
[GeneratedRegex(@\[(.)\])] private static partial Regex CrateRegex();
protected override void Solve(string[] lines)
{
One = SetupAndMoveCrates(lines, false);
Two = SetupAndMoveCrates(lines, true);
}
private static string SetupAndMoveCrates(string[] lines, bool moveAsGroup)
{
var idx = lines.ToList().FindIndex(string.IsNullOrWhiteSpace);
var crateLines = lines[..idx];
var instructions = lines[(idx + 1)..];
var stacks = Enumerable.Range(0, crateLines.Last().Last(char.IsDigit) - '0')
.Select((x, stackIdx) => new Stack<char>(crateLines.Reverse().Skip(1)
.Select(crateLine => crateLine
.Chunk(4)
.Skip(stackIdx)
.Select(crateStr => CrateRegex().Match(string.Concat(crateStr))
.Groups.Values.Last().Value.FirstOrDefault())
.FirstOrDefault())
.Where(x => x > 0)))
.ToArray();
MoveCrates(instructions, stacks, moveAsGroup);
return string.Concat(stacks.Select(x => x.Peek()));
}
private static void MoveCrates(IEnumerable<string> instructions, Stack<char>[] stacks, bool moveAsGroup)
{
foreach (var instruction in instructions)
{
var values = InstructionRegex().Match(instruction).Groups.Values
.Skip(1).Select(x => int.Parse(x.Value)).ToList();
var (amount, from, to) = (values[0], values[1], values[2]);
var crates = Enumerable.Range(0, amount).Select(_ => stacks[from - 1].Pop());
if (moveAsGroup) crates = crates.Reverse();
stacks[to - 1].PushRange(crates);
}
}
}
Dag: 5
SprÄk: C
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARRAY_LEN(x) (sizeof(x) / sizeof((x)[0]))
#define MAX_CRATES 128
#define MAX_PILES 9
struct pile {
char c[MAX_CRATES];
int n;
};
struct pile p[MAX_PILES];
struct pile p2[MAX_PILES];
void parsePiles(char *line, ssize_t len) {
int idx = 0, chr = 0;
while(++chr < len) {
if (line[chr] == ' ') {
idx++;
chr += 3;
continue;
}
memmove(p[idx].c+1, p[idx].c, p[idx].n);
p[idx].c[0] = line[chr];
p[idx].n++;
idx++;
chr+=3;
}
}
void doMoves(char *line) {
int n, from, to;
if (sscanf(line, "move %d from %d to %d\n", &n, &from, &to) != 3)
exit(EXIT_FAILURE);
from--;
to--;
// Part 1
for (int i=0; i<n; i++)
p[to].c[p[to].n++] = p[from].c[--p[from].n];
// Part 2
p2[from].n -= n;
memcpy(&p2[to].c[p2[to].n], &p2[from].c[p2[from].n], n);
p2[to].n += n;
}
int main(void) {
char *line = NULL;
size_t len = 0;
ssize_t nread;
FILE *fp = fopen("d5_input.txt", "r");
if (!fp) {
perror("Failed to open file");
exit(EXIT_FAILURE);
}
while ((nread = getline(&line, &len, fp)) != -1) {
if (!strcmp(line, "\n"))
break;
if (strncmp(line, " ", 3) && strncmp(line, "[", 1))
continue;
parsePiles(line, nread);
}
memcpy(p2, p, sizeof(p));
while ((nread = getline(&line, &len, fp)) != -1)
doMoves(line);
printf("Answer string for part 1: ");
for (int i=0; i<ARRAY_LEN(p); i++)
putchar(p[i].c[p[i].n-1]);
putchar('\n');
printf("Answer string for part 2: ");
for (int i=0; i<ARRAY_LEN(p2); i++)
putchar(p2[i].c[p2[i].n-1]);
putchar('\n');
free(line);
fclose(fp);
exit(EXIT_SUCCESS);
}
- IgĂ„r AMD, Nvidia och Intel â vad Ă€r det för skillnad mellan grafikkortstillverkarna? 9
- IgÄr Testpilot: MSI MPG 271QRX - FÀrgsprakande OLED i 360 Hz 13
- 23 / 4 Meta öppnar upp Quests OS â vill bli VR-vĂ€rldens Android 12
- 23 / 4 Googles nÀsta Chromecast fÄr dubblerad lagring 74
- 23 / 4 EK Water Blocks lovar bot och bÀttring 16
- IgÄr Valve tÀpper till kryphÄl i Steam-Äterbetalningar 18
- IgÄr Microsoft blockerar Àldre processorer i Windows 11 24H2 36
- 23 / 4 Tiny11 gör Windows 11-installationen lÀtt 28
- 23 / 4 Enklare installera Windows-program frÄn webben 15
- 22 / 4 Valve uppdaterar Team Fortress 2 med 64âbitarsstöd 22
- IgÄr Viaplay sÀtter ner foten mot delade konton 30
- IgÄr Systembolaget varnar: Dryckesbrist efter hackerattack 58
- IgÄr Veckans frÄga: Hur mycket lagringsutrymme har din dator? 81
- IgÄr Google skjuter pÄ utfasning av tredjepartskakor till 2025 16
- IgÄr Skadlig kod sprids via lömska Github-lÀnkar 13
- Mini PC som klarar 4K 120Hz över HDMI7
- Nyhetstips!425
- Veckans frÄga: Hur mycket lagringsutrymme har din dator?82
- Systembolaget varnar: Dryckesbrist efter hackerattack58
- TrÄden om PlayStation 514570
- Kan inte ansluta "smart-plug" till ny Telia router Technicolor EWA 133010
- Viaplay sÀtter ner foten mot delade konton30
- TrÄden för 2-kanals stereo med högtalare642
- Ny TV har skada i panel, butik menar att de inte kan Ă„terskapa felet21
- GamingskÀrm - ultrawide eller inte?19
- Köpes i7 12th 13 14 gen
- SĂ€ljes 64 Gig DDR5 2x32Gig, 6000MT/s CL36-38-38 1.35V EXPO/XMP
- SĂ€ljes Gamingdator I9-13900KF - 7800 XT - Z690 - DDR5 32GB - Define 7
- SĂ€ljes T700 2TB M2 SSD. Lian Li Strimer 24pin. Vertical mount
- SĂ€ljes Dell Poweredge R330
- Bytes 3070 MSI Suprim X mot Strix
- SĂ€ljes Sapphire pulse 6700xt
- SĂ€ljes XPS 9370
- SĂ€ljes Gigabyte GeForce RTX 4080 16GB GAMING OC
- SÀljes Gamingtillbehör - HyperX, Logitech
- Viaplay sÀtter ner foten mot delade konton30
- AMD, Nvidia och Intel â vad Ă€r det för skillnad mellan grafikkortstillverkarna?9
- Systembolaget varnar: Dryckesbrist efter hackerattack58
- Veckans frÄga: Hur mycket lagringsutrymme har din dator?82
- Valve tÀpper till kryphÄl i Steam-Äterbetalningar18
- Testpilot: MSI MPG 271QRX - FĂ€rgsprakande OLED i 360Â Hz13
- Google skjuter pÄ utfasning av tredjepartskakor till 202516
- Skadlig kod sprids via lömska Github-lÀnkar13
- Microsoft blockerar Àldre processorer i Windows 11 24H236
- Meta öppnar upp Quests OS â vill bli VR-vĂ€rldens Android12