đŸ•Żïž Advent of Code 2019 đŸ•Żïž

PermalÀnk
Medlem
●

Kunde ÄteranvÀnda det mesta frÄn dag 2. Det lönade sig att vara lite generell.

Dag: 5
SprÄk: Haskell
Lösning: 1 & 2

{-# LANGUAGE LambdaCase, TemplateHaskell, TypeApplications #-} module Day5 (part1, part2) where import Control.Monad.State import Control.Applicative import Data.List.Split import Lens.Micro.Platform (makeLenses, use, to, modifying, (<<%=), assign) import Data.Sequence (Seq) import Data.Composition import qualified Data.Sequence as Seq newtype Addr = Addr Int deriving (Ord, Eq) type Pc = Int type Mem = Seq Int data St = St { _pc :: Pc, _mem :: Mem } makeLenses ''St type Eval a = StateT St IO a part1 :: IO Int part1 = do putStrLn "Enter \"1\" at first prompt" (run . parse) =<< readInput part2 :: IO Int part2 = do putStrLn "Enter \"5\" at first prompt" (run . parse) =<< readInput readInput :: IO String readInput = readFile "inputs/day-5" parse :: String -> Mem parse = Seq.fromList . fmap read . splitOn "," run :: Mem -> IO Int run = evalStateT eval . St 0 eval :: Eval Int eval = step >>= \case Just x -> pure x Nothing -> eval step :: Eval (Maybe Int) step = do (opcode, modes) <- nextInstr let binop' = binop (modes !! 0) (modes !! 1) let jmpIf' = jmpIf (modes !! 0) (modes !! 1) case opcode of 1 -> binop' (+) 2 -> binop' (*) 3 -> input 4 -> output (modes !! 0) 5 -> jmpIf' (/= 0) 6 -> jmpIf' (== 0) 7 -> binop' (fromEnum .* (<)) 8 -> binop' (fromEnum .* (==)) 99 -> pure () _ -> error "Undefined opcode" if opcode == 99 then fmap Just (load (Addr 0)) else pure Nothing where nextInstr = fmap (\x -> (extractOpcode x, extractModes x)) next extractOpcode x = mod x 100 extractModes x = map (\n -> mod (div x (10 ^ n)) 10) [2 :: Int ..] next = load . Addr =<< (pc <<%= (+ 1)) binop amode bmode f = do v <- liftA2 f (getArg amode) (getArg bmode) dst <- nextAddr store dst v input = do v <- lift (putStr "input> " >> fmap (read @Int) getLine) dst <- nextAddr store dst v output mode = getArg mode >>= \x -> lift (putStrLn ("output: " ++ show x)) jmpIf amode bmode pred = do (a, b) <- liftA2 (,) (getArg amode) (getArg bmode) when (pred a) (assign pc b) getArg = \case 0 -> load =<< nextAddr -- Address mode 1 -> next -- Immediate mode _ -> error "Undefined mode" nextAddr = fmap Addr next store :: Addr -> Int -> Eval () store (Addr i) = modifying mem . Seq.update i load :: Addr -> Eval Int load (Addr i) = use (mem . to (flip Seq.index i))

Dold text
Visa signatur

Arbets- / Spelstation: Arch Linux - Ryzen 5 3600 - RX 7900 XT - 32G DDR4
Server: Arch Linux - Core i5-10400F - 16G DDR4

PermalÀnk
Medlem ★
●

Det hÀr var ju en rolig adventskalender Hoppas tiden rÀcker till att göra alltihop.

Min lösning pÄ Dag 1 i C#

private void CalculateButton_Click(object sender, EventArgs e) { string[] modules = InputTextBox.Text.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); double totalFuel = 0; foreach (string module in modules) { totalFuel += CalculateFuel(double.Parse(module)); } ResultTextBox.Text = totalFuel.ToString(); } private double CalculateFuel(double mass) { double fuel = Math.Floor(mass / 3) - 2; if (fuel > 0) { return fuel + CalculateFuel(fuel); } return 0; }

Dold text
PermalÀnk
Datavetare ★
●

Rust - dag 5

Skrivet av Daz:

Hur fÄr ni de snygga fÀrgerna i koden? Min ser helt livlös ut i jÀmförelse.

Tror du redan fÄtt en fullgott svar pÄ din frÄga. Men om du vill ha fler alternativ, jag anvÀnder ett projekt som heter Highlight som verkar kunna hantera de flesta nÄgorlunda populÀra programsprÄk.

Idag hade jag en konversation med Rusts borrow-checker. Som C/C++ ser man direkt hur extremt vÀrdefull denna finess (saknas i C/C++) Àr för att förhindra potentiellt svÄrfunna buggar!

use super::Solution; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use Instruction::*; type Intcode = i32; #[derive(Debug, FromPrimitive)] enum Instruction { Add = 1, Mul = 2, In = 3, Out = 4, JmpIfTrue = 5, JmpIfFalse = 6, LessThan = 7, Equals = 8, Halt = 99, } // State required to solve day 5 pub struct State { memory: Vec<Intcode>, } fn run(memory: &Vec<Intcode>, input: &mut dyn Iterator<Item = Intcode>) -> Vec<Intcode> { let mut mem = memory.clone(); let mut ip: usize = 0; let mut output = Vec::new(); loop { let mut st = None; { let opcode = mem[ip]; let is_imm = [ false, opcode / 100 % 10 != 0, opcode / 1000 % 10 != 0, opcode / 10000 % 10 != 0, ]; let ld_imm = |offset| mem[ip + offset as usize]; let ld = |offset| { if is_imm[offset] { ld_imm(offset) } else { mem[ld_imm(offset) as usize] } }; ip = match FromPrimitive::from_i32(opcode % 100).expect("Invalid instruction") { Add => { st = Some((ld(1) + ld(2), ld_imm(3))); ip + 4 } Mul => { st = Some((ld(1) * ld(2), ld_imm(3))); ip + 4 } In => { st = Some((input.next().unwrap(), ld_imm(1))); ip + 2 } Out => { output.push(ld(1)); ip + 2 } JmpIfTrue => { if ld(1) != 0 { ld(2) as usize } else { ip + 3 } } JmpIfFalse => { if ld(1) == 0 { ld(2) as usize } else { ip + 3 } } LessThan => { st = Some((if ld(1) < ld(2) { 1 } else { 0 }, ld_imm(3))); ip + 4 } Equals => { st = Some((if ld(1) == ld(2) { 1 } else { 0 }, ld_imm(3))); ip + 4 } Halt => { return output; } } } // All immutable borrows must go out of scope before it is OK to store // to 'mem', so this kind of simulates "write-back" step in a CPU... if let Some((val, addr)) = st { mem[addr as usize] = val; } } } impl Solution for State { fn part1(&self) -> String { let input: Vec<Intcode> = vec![1]; run(&self.memory, &mut input.into_iter()) .last() .unwrap() .to_string() } fn part2(&self) -> String { let input: Vec<Intcode> = vec![5]; run(&self.memory, &mut input.into_iter()) .last() .unwrap() .to_string() } } pub fn solution(lines: Vec<&str>) -> Box<dyn Solution> { Box::new(State { memory: lines[0] .split(",") .map(|ic| ic.parse::<Intcode>().unwrap()) .collect(), }) }

SmÄsaker kvar frÄn dag 2, men som grön Rust-programmerare som lÀr sig för varje dag Àr det inte konstigt att man vill göra saker annorlunda med tiden...

UtgÄr frÄn att datorn kommer tillbaka, lade in stöd för multipla inputs och outputs redan nu.

Visa signatur

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

PermalÀnk
●

Dag 5 - Kotlin

tailrec fun run(program: Array<Int>, position: Int, output: MutableList<Int>, input: Int? = null): List<Int> { val instruction = program[position] val operation = instruction % 100 val paramMode1 = instruction / 100 % 10 == 1 val paramMode2 = instruction / 1000 % 10 == 1 return when (operation) { 1, 2 -> { val param1 = if (paramMode1) program[position + 1] else program[program[position + 1]] val param2 = if (paramMode2) program[position + 2] else program[program[position + 2]] program[program[position + 3]] = if (operation == 1) param1 + param2 else param1 * param2 run(program, position + 4, output) } 3 -> { program[program[position + 1]] = input!! run(program, position + 2, output) } 4 -> { val value = if (paramMode1) program[position + 1] else program[program[position + 1]] output.add(value) run(program, position + 2, output) } 5, 6 -> { val param1 = if (paramMode1) program[position + 1] else program[program[position + 1]] val param2 = if (paramMode2) program[position + 2] else program[program[position + 2]] if ((operation == 5 && param1 != 0) || (operation == 6 && param1 == 0)) { run(program, param2, output) } else { run(program, position + 3, output) } } 7, 8 -> { val param1 = if (paramMode1) program[position + 1] else program[program[position + 1]] val param2 = if (paramMode2) program[position + 2] else program[program[position + 2]] if ((operation == 7 && param1 < param2) || (operation == 8 && param1 == param2)) { program[program[position + 3]] = 1 } else { program[program[position + 3]] = 0 } run(program, position + 4, output) } 99 -> output else -> throw RuntimeException("oh no!") }

Dold text
Visa signatur

"Knowledge amplification. What he learns, we all learn. What he knows, we all benefit from."

PermalÀnk
Medlem ★
●

Dag 2 i C#

private void RunProgramButton_Click(object sender, EventArgs e) { IntCodeComputer computer = new IntCodeComputer(); computer.Memory = Array.ConvertAll(InputTextBox.Text.Split(','), Convert.ToInt32); computer.RunProgram(); ResultTextBox.Text = computer.Memory[0].ToString(); } private void FindValuesButton_Click(object sender, EventArgs e) { IntCodeComputer computer = new IntCodeComputer(); for (int noun = 0; noun <= 99; noun++) { for (int verb = 0; verb <= 99; verb++) { computer.Memory = Array.ConvertAll(InputTextBox.Text.Split(','), Convert.ToInt32); computer.Memory[1] = noun; computer.Memory[2] = verb; computer.RunProgram(); if (computer.Memory[0] == 19690720) { ResultTextBox.Text = (100 * noun + verb).ToString(); return; } } } } class IntCodeComputer { public int[] Memory { set; get; } public void RunProgram() { int instructionPointer = 0; while (Memory[instructionPointer] != 99) { switch (Memory[instructionPointer]) { case 1: Memory[Memory[instructionPointer + 3]] = Memory[Memory[instructionPointer + 1]] + Memory[Memory[instructionPointer + 2]]; instructionPointer += 4; break; case 2: Memory[Memory[instructionPointer + 3]] = Memory[Memory[instructionPointer + 1]] * Memory[Memory[instructionPointer + 2]]; instructionPointer += 4; break; default: throw new Exception("Unknown opcode. Aborting."); } } } }

Dold text
PermalÀnk
Medlem ★
●

Inte precis den snyggaste lösningen men har haft lite brist pÄ tid (dÀrför jag ocksÄ Àr en dag efter)

Dag: 4
SprÄk: Powershell
Lösning: Del 1 + 2

$StartNumber = 171309 $EndNumber = 643603 $DoubbleNumberArray = @() [int]$StartNumber..[int]$EndNumber | ForEach-Object -Parallel { $Checker = $_.ToString().ToCharArray() ## Does password include a doubble? if( $_ -match "11|22|33|44|55|66|77|88|99|00" -and ($Checker[5] -ge $Checker[4]) -and ($Checker[4] -ge $Checker[3]) -and ($Checker[3] -ge $Checker[2]) -and ($Checker[2] -ge $Checker[1]) -and ($Checker[1] -ge $Checker[0]) ) { Write-Output $_ $DoubbleNumberArray += $Checker } } $DoubbleNumberArray.Count

Dold text

$NewNumberArray = @() $Index = 0 $DoubbleNumberArray | ForEach-Object { $Digicount0 = ((($_.ToString()).ToCharArray()) | ? {$_ -eq '0'} | Measure-Object -ErrorAction SilentlyContinue).Count $Digicount1 = ((($_.ToString()).ToCharArray()) | ? {$_ -eq '1'} | Measure-Object -ErrorAction SilentlyContinue).Count $Digicount2 = ((($_.ToString()).ToCharArray()) | ? {$_ -eq '2'} | Measure-Object -ErrorAction SilentlyContinue).Count $Digicount3 = ((($_.ToString()).ToCharArray()) | ? {$_ -eq '3'} | Measure-Object -ErrorAction SilentlyContinue).Count $Digicount4 = ((($_.ToString()).ToCharArray()) | ? {$_ -eq '4'} | Measure-Object -ErrorAction SilentlyContinue).Count $Digicount5 = ((($_.ToString()).ToCharArray()) | ? {$_ -eq '5'} | Measure-Object -ErrorAction SilentlyContinue).Count $Digicount6 = ((($_.ToString()).ToCharArray()) | ? {$_ -eq '6'} | Measure-Object -ErrorAction SilentlyContinue).Count $Digicount7 = ((($_.ToString()).ToCharArray()) | ? {$_ -eq '7'} | Measure-Object -ErrorAction SilentlyContinue).Count $Digicount8 = ((($_.ToString()).ToCharArray()) | ? {$_ -eq '8'} | Measure-Object -ErrorAction SilentlyContinue).Count $Digicount9 = ((($_.ToString()).ToCharArray()) | ? {$_ -eq '9'} | Measure-Object -ErrorAction SilentlyContinue).Count $NewNumberArray += [pscustomobject]@{ Index = $index Number = 0 Count = [pscustomobject]@{ "0" = $Digicount0;"1" = $Digicount1;"2" = $Digicount2;"3" = $Digicount3;"4" = $Digicount4;"5" = $Digicount5;"6" = $Digicount6;"7" = $Digicount7;"8" = $Digicount8;"9" = $Digicount9 } IncomingValue = $_ } $Index++ } $FinalNumberList = $NewNumberArray | Where-Object { $_.Count.0 -eq 2 -or $_.Count.1 -eq 2 -or $_.Count.2 -eq 2 -or $_.Count.3 -eq 2 -or $_.Count.4 -eq 2 -or $_.Count.5 -eq 2 -or $_.Count.6 -eq 2 -or $_.Count.7 -eq 2 -or $_.Count.8 -eq 2 -or $_.Count.9 -eq 2 } $FinalNumberList.Count

Dold text
Visa signatur

🟱 Main: Ryzen7 5800X | Strix x470-I | 32GB | RTX2070S | Samsung C49RG9
đŸ”” unRaid: Ryzen5 2700X | B450M DS3H | 32GB
🟠 Tfn: Google Pixel 7 Lime Green

-:| @ eller citera för svar |:-

PermalÀnk
Datavetare ★
●

Rust - dag 6

Fick göra denna nu, Àr ju nördöl senare ikvÀll

use super::Solution; use std::collections::HashMap; use std::collections::HashSet; use std::iter::FromIterator; // State required to solve day 6 pub struct State { orbiting: HashMap<String, String>, } pub fn solution(lines: Vec<&str>) -> Box<dyn Solution> { Box::new(State { orbiting: lines .iter() .map(|line| { let mut s = line.split(")"); let center = s.next().unwrap().to_string(); let satellite = s.next().unwrap().to_string(); (satellite, center) }) .collect(), }) } // Body centers, from outermost satellite body to world center body fn centers(orbiting: &HashMap<String, String>, outermost: &String) -> Vec<String> { let mut satellite = Some(outermost); let mut cntrs = Vec::new(); while let Some(sat) = satellite { cntrs.push(sat.clone()); satellite = orbiting.get(sat); } cntrs } impl Solution for State { fn part1(&self) -> String { let total_orbits: u32 = self.orbiting .values() .map(|sat| centers(&self.orbiting, sat).len() as u32) .sum(); total_orbits.to_string() } fn part2(&self) -> String { let you = centers(&self.orbiting, &"YOU".to_string()); let san = centers(&self.orbiting, &"SAN".to_string()); let ys: HashSet<String> = HashSet::from_iter(you.into_iter().skip(1)); let ss: HashSet<String> = HashSet::from_iter(san.into_iter().skip(1)); ys.symmetric_difference(&ss).count().to_string() } }

En hel del kvar att lÀra kring bÀsta hantering av strÀngar i Rust...
Visa signatur

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

PermalÀnk
●

Dag 6 i Kotlin

private fun parse(input: List<String>): List<Pair<String, String>> = input.map { it.split(")") }.map { Pair(it[0], it[1]) } private fun orbitCount(map: Map<String, Set<String>>, positions: Set<String>, depth: Int = 1): Int { return if (positions.isEmpty()) { 0 } else { val next = positions.flatMap { map[it] ?: emptySet() }.toSet() next.size * depth + orbitCount(map, next, depth + 1) } } private fun distance(map: Map<String, Set<String>>, reach: Set<String>, destination: String): Int { return if (reach.contains(destination)) { 0 } else { val next = reach.flatMap { map[it] ?: emptySet() }.toSet() 1 + distance(map, reach + next, destination) } } fun part1(input: List<String>, start: String): Int { val orbitMap = parse(input).foldRight(emptyMap<String, Set<String>>(), { pair, acc -> acc + Pair(pair.first, (acc[pair.first] ?: emptySet()) + pair.second) }) return orbitCount(orbitMap, setOf(start)) } fun part2(input: List<String>, start: String, destination: String): Int { val orbitMap = parse(input).foldRight(emptyMap<String, Set<String>>(), { orbit, acc -> acc + Pair(orbit.first, (acc[orbit.first] ?: emptySet()) + orbit.second) + Pair(orbit.second, (acc[orbit.second] ?: emptySet()) + orbit.first) }) return distance(orbitMap, orbitMap[start]!!, orbitMap[destination]!!.first()) }

Dold text
Visa signatur

"Knowledge amplification. What he learns, we all learn. What he knows, we all benefit from."

PermalÀnk
Medlem
●

Dag: 6

Scala:

val input = Using.resource(Source.fromFile(path.toFile))(_.getLines().map { case s"${x})${y}" => y -> x }.toMap) val parents: String => Set[String] = Set.unfold(_)(input.get(_).map(p => p -> p)) input.keysIterator.map(parents(_).size).sum.pipe(println) val (pYou, pSan) = (parents("YOU"), parents("SAN")) (pYou.size + pSan.size - 2 * (pYou & pSan).size).pipe(println)

Dold text

Ett försök till ungefÀr samma kod i Dyalog APL:

v k←↓⍉↑')'(≠⊆⊱)¹⊃⎕NGET'day06.txt'1 l←{v⌷⍚kâłâ”} ⋄ p←{{â”â‰ąâŠ‚'COM':⍔,∇l⍔⋄⍔}l⊂⍔} +/{⊃≱p⍔}šk ⍝ del 1 py←p'YOU' ⋄ ps←p'SAN' (⍎ps)+(⍎py)-2×⍮ps∩py ⍝ del 2

Dold text
PermalÀnk
Medlem
●

Ajaj, missade en smart insikt som nÄgra av er andra hade hÀr, sÄ blev en lite naïv lösning.

Dag: 6
SprÄk: Haskell

Smart av er att inse att man bara kan subtrahera lÀngden pÄ det gemensamma prefixet eftersom det Àr ett trÀd! SÄ lÄngt tÀnkte inte jag, sÄ det blev en nÄgot mer naïv breadth-first search.

{-# LANGUAGE TupleSections #-} module Day6 (part1, part2) where import Data.List.Split import Data.Map (Map) import qualified Data.Map as Map import Data.Bifunctor import Data.Tuple import Data.Sequence (Seq, (><)) import qualified Data.Sequence as Seq import Data.Set (Set) import qualified Data.Set as Set import Lib type Body = String type OrbitedBy = Map Body [Body] -- Part1 part1 :: IO Int part1 = fmap (countOrbits "COM" 0 . parse1) readInput readInput :: IO String readInput = readFile "inputs/day-6" parse1 :: String -> OrbitedBy parse1 = Map.fromListWith (++) . map (second pure . head2 . splitOn ")") . lines countOrbits :: Body -> Int -> OrbitedBy -> Int countOrbits a l os = l + case Map.lookup a os of Just bs -> sum (map (\b -> countOrbits b (l + 1) os) bs) Nothing -> 0 -- Part 2 part2 :: IO Int part2 = fmap (\inp -> (bfs "YOU" "SAN" (parse2 inp)) - 2) readInput -- | Returns a directed graph with both forward- and backward-edges for each -- orbit. parse2 :: String -> Map Body [Body] parse2 s = let forws = map (head2 . splitOn ")") (lines s) backws = map swap forws in Map.fromListWith (++) (map (second pure) (forws ++ backws)) bfs :: Body -> Body -> Map Body [Body] -> Int bfs a = bfs' Set.empty (Seq.singleton (a, 0)) bfs' :: Set Body -> Seq (Body, Int) -> Body -> Map Body [Body] -> Int bfs' visited as b os = let ((a, l), as') = viewl' as in if Set.member a visited then bfs' visited as' b os else if a == b then l else bfs' (Set.insert a visited) (as' >< Seq.fromList (map (, l + 1) (os Map.! a))) b os viewl' :: Seq a -> (a, Seq a) viewl' xs = case Seq.viewl xs of Seq.EmptyL -> error "viewl' of empty Seq" x Seq.:< xs' -> (x, xs')

Dold text
Visa signatur

Arbets- / Spelstation: Arch Linux - Ryzen 5 3600 - RX 7900 XT - 32G DDR4
Server: Arch Linux - Core i5-10400F - 16G DDR4

PermalÀnk
●

RÀtt bra flyt idag. 07:58 för första och 15:18 för andra. Python 3.

def solve(d): graph = {} for line in d: a, b = line.split(')') graph[b] = a if a not in graph: graph[a] = 'STOP' count = 0 for node in graph.keys(): while node in graph and graph[node] in graph: count += 1 node = graph[node] return count

Dag 6a

def pathize(graph, node): path = {} runlen = 0 while node in graph: runlen += 1 node = graph[node] path[node] = runlen return path def solve(d): graph = {} for line in d: a, b = line.split(')') graph[b] = a if a not in graph: graph[a] = 'STOP' you_orbits = pathize(graph, graph['YOU']) san_orbits = pathize(graph, graph['SAN']) best = 10**10 for k, v in you_orbits.items(): if k not in san_orbits: continue best = min(best, v + san_orbits[k]) return best

Dag 6b
PermalÀnk
Medlem ★
●

Dag 6
SprÄk C#
Del 1&2
Hade inte lÀtt med subfunktionell biologisk cpu idag. Blev lÄngt och tradigt, men kördes pÄ 150 respektive 150 miliisekunder.

public Dictionary<string,string> GetPaths(Dictionary<string,string> comDaughter) { Dictionary<string, string> daughterPath = new Dictionary<string, string>(); foreach (KeyValuePair<string, string> item in comDaughter) { bool hasParent = true; string path = item.Value + Path.DirectorySeparatorChar + item.Key; string curParent = item.Value; while (hasParent) { if (comDaughter.ContainsKey(curParent)) { curParent = comDaughter[curParent]; path = curParent + Path.DirectorySeparatorChar + path; } else { hasParent = false; } } daughterPath.Add(item.Key, path); } return daughterPath; } public Dictionary<string, string> GetParents(List<string> lines) { Dictionary<string, string> comDaughter = new Dictionary<string, string>(); foreach (string line in lines) { string com = line.Split(')')[0]; string daughter = line.Split(')')[1]; comDaughter.Add(daughter, com); } return comDaughter; } private OrbitalMap GetOrbitalMap(Dictionary<string,string> daughterPaths) { OrbitalMap orbitalMap = new OrbitalMap(); foreach (KeyValuePair<string,string> item in daughterPaths) { orbitalMap.Add(item.Value); } return orbitalMap; } private void button6_Click(object sender, EventArgs e) { System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew(); List<string> lines = GetLines(txtInput.Text); Dictionary<string, string> comDaughter = GetParents(lines); Dictionary<string, string> daughterPaths = GetPaths(comDaughter); OrbitalMap orbitalMap = GetOrbitalMap(daughterPaths); if (this.numSubTask.Value==1) { txtAnswer.Text = orbitalMap.OrbitCount.ToString(); } else { txtInput.AppendText(System.Environment.NewLine + orbitalMap.GetPath("YOU")); txtInput.AppendText(System.Environment.NewLine + orbitalMap.GetPath("SAN")); int distance = orbitalMap.GetDistance("YOU", "SAN"); txtAnswer.Text = distance.ToString(); } watch.Stop(); Int64 elapsedMs = watch.ElapsedMilliseconds; label1.Text = elapsedMs.ToString(); } public class BodyOfMass { private string _ID = String.Empty; private string _Parent = String.Empty; private string _Path = String.Empty; public BodyOfMass(string path) { string[] parts = path.Split(Path.DirectorySeparatorChar); string parentPath = String.Empty; if (parts.Length>1) { parentPath = path.Substring(0, path.Length - path.Length); } string id = parts[parts.Length - 1]; this._ID = id; _Parent = String.Empty; _Path = path; if (!String.IsNullOrEmpty(parentPath)) { _Parent = parentPath.Split(Path.DirectorySeparatorChar)[parentPath.Split(Path.DirectorySeparatorChar).Length-1]; } } public int DistanceFromCOM { get { return _Path.Split(Path.DirectorySeparatorChar).Length - 1; } } public string ID { get { return _ID; } } public string OrbitalPath { get { return _Path; } } public string Parent { get { return _Parent; } } } public class OrbitalMap { Dictionary<string, BodyOfMass> _mine; public OrbitalMap() { _mine = new Dictionary<string, BodyOfMass>(); } public void Add(String path) { string[] parts = path.Split(Path.DirectorySeparatorChar); string curPath = string.Empty; for (int i = 0; i < parts.Length; i++) { if (i == 0) { curPath = parts[0]; } else { curPath = curPath + Path.DirectorySeparatorChar + parts[i]; } if (!_mine.ContainsKey(parts[i])) { BodyOfMass newPlanet = new BodyOfMass(curPath); _mine.Add(parts[i],newPlanet); } } } public int Count { get { return _mine.Count; } } public int OrbitCount { get { int i = 0; foreach (KeyValuePair<string,BodyOfMass> item in _mine) { i = i + item.Value.DistanceFromCOM; } return i; } } public string GetPath(string id) { return _mine[id].OrbitalPath; } public int GetDistance(string id1, string id2) { string path1 = _mine[id1].OrbitalPath; string path2 = _mine[id2].OrbitalPath; string[] pathParts1 = path1.Split(Path.DirectorySeparatorChar); string[] pathParts2 = path2.Split(Path.DirectorySeparatorChar); Dictionary<string, int> idLevel1 = new Dictionary<string, int>(); for (int i = 0; i < pathParts1.Length; i++) { idLevel1.Add(pathParts1[i], i); } Dictionary<string, int> idLevel2 = new Dictionary<string, int>(); for (int i = 0; i < pathParts2.Length; i++) { idLevel2.Add(pathParts2[i], i); } int curLevel1 = pathParts1.Length - 1; int curLevel2 = pathParts2.Length - 1; bool foundInterSection = false; while (curLevel1>-1 && !foundInterSection) { if (idLevel2.ContainsKey(pathParts1[curLevel1])) { foundInterSection = true; curLevel2 = idLevel2[pathParts1[curLevel1]]; } else { curLevel1 = curLevel1 - 1; } } int distance = pathParts1.Length - 1 + pathParts2.Length - 1 - curLevel1 - curLevel2 - 2; return distance; } }

Dold text
PermalÀnk
Medlem ★
●

KÀnns som ingen annan publicerar komplett kod... Blir ju lite mycket i mina inlÀgg. Var drar ni grÀnsen?

Annan frÄga, det skulle vara kul att se exekveringstider pÄ andra sprÄk. Jag mÀter mina i debuglÀge. Körs pÄ en intel Core i7 6700K oklockad.

PermalÀnk
●

Nedan kod Àr för första uppgiften. Byt ut parametrarna pÄ anropet till solve() för att lösa b-uppgiften.

Jag borde förresten döpa om funktionen solve_amp().

Jag borde Àven kapsla in min Intcode-dator pÄ nÄgot vis. Men det Àr lite jobbigare.

import re from heapq import heappop, heappush from collections import Counter, defaultdict from itertools import permutations def solve_amp(d, p, inputs): inp_pos = 0 while p < len(d): a = -1 if p > len(d) - 2 else d[p + 1] if ((d[p] % 1000) // 100) == 1 else d[d[p + 1]] b = -1 if p > len(d) - 3 else d[p + 2] if ((d[p] % 10000) // 1000) == 1 else -1 if d[p + 2] >= len(d) else d[d[p + 2]] if d[p] % 100 == 99: return d[0], d, 0, True if d[p] % 100 == 1: d[d[p + 3]] = a + b p += 4 elif d[p] % 100 == 2: d[d[p + 3]] = a * b p += 4 elif d[p] % 100 == 3: d[d[p + 1]] = inputs[inp_pos] inp_pos = 1 p += 2 elif d[p] % 100 == 4: if a != 0: return a, d, p + 2, False p += 2 elif d[p] % 100 == 5: if a != 0: p = b else: p += 3 elif d[p] % 100 == 6: if a == 0: p = b else: p += 3 elif d[p] % 100 == 7: c = 1 if a < b else 0 d[d[p + 3]] = c p += 4 elif d[p] % 100 == 8: c = 1 if a == b else 0 d[d[p + 3]] = c p += 4 def solve(d, lo, hi, ampcount): best = 0 for perm in permutations(range(lo, hi)): ds = [list(d) for _ in range(ampcount)] pointers = [0 for _ in range(ampcount)] val = 0 pos = 0 prev = 0 while True: data = ds[pos % ampcount] pointer = pointers[pos % ampcount] inputs = (perm[pos] if pos < ampcount else val, val) val, dp, p, finished = solve_amp(data, pointer, inputs) ds[pos % ampcount] = dp pointers[pos % ampcount] = p if finished: best = max(best, prev) break prev = val pos += 1 return best def read_and_solve(): with open('input_7.txt') as f: data = list(map(int, f.readline().split(','))) return solve(data, 0, 5, 5) if __name__ == '__main__': print(read_and_solve())

Dag 7
PermalÀnk
●
Skrivet av Mordekai:

KÀnns som ingen annan publicerar komplett kod... Blir ju lite mycket i mina inlÀgg. Var drar ni grÀnsen?

Annan frÄga, det skulle vara kul att se exekveringstider pÄ andra sprÄk. Jag mÀter mina i debuglÀge. Körs pÄ en intel Core i7 6700K oklockad.

Tycker inte körtiderna Àr sÀrskilt intressanta Àn sÄ lÀnge. Men det blir vÀl vÀrre lÀngre fram.

❯ pytest --durations=0 ================================================================================================== test session starts ================================================================================================== platform win32 -- Python 3.7.3, pytest-5.3.1, py-1.8.0, pluggy-0.13.1 rootdir: C:\Users\chris\source\repos\advent_of_code_2019\estomagordo-python3 collected 14 items test_correctness.py .............. [100%] ================================================================================================ slowest test durations ================================================================================================= 0.64s call test_correctness.py::test_4b 0.56s call test_correctness.py::test_4a 0.18s call test_correctness.py::test_3a 0.17s call test_correctness.py::test_3b 0.09s call test_correctness.py::test_2b 0.04s call test_correctness.py::test_7b 0.02s call test_correctness.py::test_6a 0.01s call test_correctness.py::test_7a (0.00 durations hidden. Use -vv to show these durations.)

PermalÀnk
●

Day 7 i Kotlin

tailrec fun run(program: Array<Int>, position: Int, output: MutableList<Int>, input: List<Int>): List<Int> { val instruction = program[position] val operation = instruction % 100 val paramMode1 = instruction / 100 % 10 == 1 val paramMode2 = instruction / 1000 % 10 == 1 return when (operation) { 1, 2 -> { val param1 = if (paramMode1) program[position + 1] else program[program[position + 1]] val param2 = if (paramMode2) program[position + 2] else program[program[position + 2]] program[program[position + 3]] = if (operation == 1) param1 + param2 else param1 * param2 run(program, position + 4, output, input) } 3 -> { program[program[position + 1]] = input[0] run(program, position + 2, output, input.drop(1)) } 4 -> { val value = if (paramMode1) program[position + 1] else program[program[position + 1]] output.add(value) run(program, position + 2, output, input) } 5, 6 -> { val param1 = if (paramMode1) program[position + 1] else program[program[position + 1]] val param2 = if (paramMode2) program[position + 2] else program[program[position + 2]] if ((operation == 5 && param1 != 0) || (operation == 6 && param1 == 0)) { run(program, param2, output, input) } else { run(program, position + 3, output, input) } } 7, 8 -> { val param1 = if (paramMode1) program[position + 1] else program[program[position + 1]] val param2 = if (paramMode2) program[position + 2] else program[program[position + 2]] if ((operation == 7 && param1 < param2) || (operation == 8 && param1 == param2)) { program[program[position + 3]] = 1 } else { program[program[position + 3]] = 0 } run(program, position + 4, output, input) } 99 -> output else -> throw RuntimeException("oh no!") } } fun part1(program: Array<Int>): Int? { return permutations .map { phasePermutation -> phasePermutation.fold(0) { input, phase -> run(program.copyOf(), 0, mutableListOf(), listOf(phase, input)).last() } } .max() } class Amplifier(private val program: Array<Int>) { var position: Int = 0 val input = mutableListOf<Int>() fun addInput(value: Int): Amplifier { input.add(value) return this } fun getOutput(): Int? = execute() private tailrec fun execute(): Int? { val instruction = program[position] val operation = instruction % 100 val paramMode1 = instruction / 100 % 10 == 1 val paramMode2 = instruction / 1000 % 10 == 1 return when (operation) { 1, 2 -> { val param1 = if (paramMode1) program[position + 1] else program[program[position + 1]] val param2 = if (paramMode2) program[position + 2] else program[program[position + 2]] program[program[position + 3]] = if (operation == 1) param1 + param2 else param1 * param2 position += 4 execute() } 3 -> { program[program[position + 1]] = input.removeAt(0) position += 2 execute() } 4 -> { val value = if (paramMode1) program[position + 1] else program[program[position + 1]] position += 2 value } 5, 6 -> { val param1 = if (paramMode1) program[position + 1] else program[program[position + 1]] val param2 = if (paramMode2) program[position + 2] else program[program[position + 2]] position = if ((operation == 5 && param1 != 0) || (operation == 6 && param1 == 0)) param2 else position + 3 execute() } 7, 8 -> { val param1 = if (paramMode1) program[position + 1] else program[program[position + 1]] val param2 = if (paramMode2) program[position + 2] else program[program[position + 2]] if ((operation == 7 && param1 < param2) || (operation == 8 && param1 == param2)) { program[program[position + 3]] = 1 } else { program[program[position + 3]] = 0 } position += 4 execute() } 99 -> null else -> throw RuntimeException("oh no!") } } } fun part2(program: Array<Int>): Int? { return permutations .map { phases -> phases.map { it + 5 } } .map { phasePermutation -> val amplifiers = phasePermutation.map { Amplifier(program.copyOf()).addInput(it) } var lastOutputNotFound = true var lastOutput: Int? = 0 while (lastOutputNotFound) { val output = amplifiers.fold(lastOutput) { input, amp -> if (input == null) null else amp.addInput(input).getOutput() } if (output == null) lastOutputNotFound = false else lastOutput = output } lastOutput!! } .max() } // Generated with List(0,1,2,3,4).permutations in Scala private val permutations: List<List<Int>> = listOf( listOf(0, 1, 2, 3, 4), listOf(0, 1, 2, 4, 3), listOf(0, 1, 3, 2, 4), listOf(0, 1, 3, 4, 2), listOf(0, 1, 4, 2, 3), listOf(0, 1, 4, 3, 2), listOf(0, 2, 1, 3, 4), listOf(0, 2, 1, 4, 3), listOf(0, 2, 3, 1, 4), listOf(0, 2, 3, 4, 1), listOf(0, 2, 4, 1, 3), listOf(0, 2, 4, 3, 1), listOf(0, 3, 1, 2, 4), listOf(0, 3, 1, 4, 2), listOf(0, 3, 2, 1, 4), listOf(0, 3, 2, 4, 1), listOf(0, 3, 4, 1, 2), listOf(0, 3, 4, 2, 1), listOf(0, 4, 1, 2, 3), listOf(0, 4, 1, 3, 2), listOf(0, 4, 2, 1, 3), listOf(0, 4, 2, 3, 1), listOf(0, 4, 3, 1, 2), listOf(0, 4, 3, 2, 1), listOf(1, 0, 2, 3, 4), listOf(1, 0, 2, 4, 3), listOf(1, 0, 3, 2, 4), listOf(1, 0, 3, 4, 2), listOf(1, 0, 4, 2, 3), listOf(1, 0, 4, 3, 2), listOf(1, 2, 0, 3, 4), listOf(1, 2, 0, 4, 3), listOf(1, 2, 3, 0, 4), listOf(1, 2, 3, 4, 0), listOf(1, 2, 4, 0, 3), listOf(1, 2, 4, 3, 0), listOf(1, 3, 0, 2, 4), listOf(1, 3, 0, 4, 2), listOf(1, 3, 2, 0, 4), listOf(1, 3, 2, 4, 0), listOf(1, 3, 4, 0, 2), listOf(1, 3, 4, 2, 0), listOf(1, 4, 0, 2, 3), listOf(1, 4, 0, 3, 2), listOf(1, 4, 2, 0, 3), listOf(1, 4, 2, 3, 0), listOf(1, 4, 3, 0, 2), listOf(1, 4, 3, 2, 0), listOf(2, 0, 1, 3, 4), listOf(2, 0, 1, 4, 3), listOf(2, 0, 3, 1, 4), listOf(2, 0, 3, 4, 1), listOf(2, 0, 4, 1, 3), listOf(2, 0, 4, 3, 1), listOf(2, 1, 0, 3, 4), listOf(2, 1, 0, 4, 3), listOf(2, 1, 3, 0, 4), listOf(2, 1, 3, 4, 0), listOf(2, 1, 4, 0, 3), listOf(2, 1, 4, 3, 0), listOf(2, 3, 0, 1, 4), listOf(2, 3, 0, 4, 1), listOf(2, 3, 1, 0, 4), listOf(2, 3, 1, 4, 0), listOf(2, 3, 4, 0, 1), listOf(2, 3, 4, 1, 0), listOf(2, 4, 0, 1, 3), listOf(2, 4, 0, 3, 1), listOf(2, 4, 1, 0, 3), listOf(2, 4, 1, 3, 0), listOf(2, 4, 3, 0, 1), listOf(2, 4, 3, 1, 0), listOf(3, 0, 1, 2, 4), listOf(3, 0, 1, 4, 2), listOf(3, 0, 2, 1, 4), listOf(3, 0, 2, 4, 1), listOf(3, 0, 4, 1, 2), listOf(3, 0, 4, 2, 1), listOf(3, 1, 0, 2, 4), listOf(3, 1, 0, 4, 2), listOf(3, 1, 2, 0, 4), listOf(3, 1, 2, 4, 0), listOf(3, 1, 4, 0, 2), listOf(3, 1, 4, 2, 0), listOf(3, 2, 0, 1, 4), listOf(3, 2, 0, 4, 1), listOf(3, 2, 1, 0, 4), listOf(3, 2, 1, 4, 0), listOf(3, 2, 4, 0, 1), listOf(3, 2, 4, 1, 0), listOf(3, 4, 0, 1, 2), listOf(3, 4, 0, 2, 1), listOf(3, 4, 1, 0, 2), listOf(3, 4, 1, 2, 0), listOf(3, 4, 2, 0, 1), listOf(3, 4, 2, 1, 0), listOf(4, 0, 1, 2, 3), listOf(4, 0, 1, 3, 2), listOf(4, 0, 2, 1, 3), listOf(4, 0, 2, 3, 1), listOf(4, 0, 3, 1, 2), listOf(4, 0, 3, 2, 1), listOf(4, 1, 0, 2, 3), listOf(4, 1, 0, 3, 2), listOf(4, 1, 2, 0, 3), listOf(4, 1, 2, 3, 0), listOf(4, 1, 3, 0, 2), listOf(4, 1, 3, 2, 0), listOf(4, 2, 0, 1, 3), listOf(4, 2, 0, 3, 1), listOf(4, 2, 1, 0, 3), listOf(4, 2, 1, 3, 0), listOf(4, 2, 3, 0, 1), listOf(4, 2, 3, 1, 0), listOf(4, 3, 0, 1, 2), listOf(4, 3, 0, 2, 1), listOf(4, 3, 1, 0, 2), listOf(4, 3, 1, 2, 0), listOf(4, 3, 2, 0, 1), listOf(4, 3, 2, 1, 0) )

Dold text

Som svar till Mordekai sÄ finns komplett kod för min del pÄ GitHub dÀr man kan köra allt rakt av (testerna lÀser inputdatan och exempeldata):
https://github.com/AntonFagerberg/advent-of-code-2019
I inlÀggen brukar jag bara ta med funktionerna, tÀnker att det Àr det man vill lÀsa.

Visa signatur

"Knowledge amplification. What he learns, we all learn. What he knows, we all benefit from."

PermalÀnk
Datavetare ★
●

Inte nöjd med dagens resultat. Kanske missförstÄtt nÄgot kring Rust, men kÀnns inte som coroutines Àr riktigt klart Àn (för den lösning jag tÀnkte pÄ ville inte kompilera p.g.a. "not a stable feature...").

use super::Solution; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use permutohedron::LexicalPermutation; use Instruction::*; use ProgState::*; type Intcode = i32; const NUM_AMPS: usize = 5; #[derive(Debug, FromPrimitive, PartialEq)] enum Instruction { Add = 1, Mul = 2, In = 3, Out = 4, JmpIfTrue = 5, JmpIfFalse = 6, LessThan = 7, Equals = 8, Halt = 99, } #[derive(Copy, Clone, Debug)] enum ProgState { Resume(usize), Done, } // State required to solve day 7 pub struct State { memory: Vec<Intcode>, } fn opcode_to_instr(opcode: Intcode) -> Instruction { FromPrimitive::from_i32(opcode % 100).expect("Invalid instruction") } fn run( mem: &mut Vec<Intcode>, input: &mut dyn Iterator<Item = Intcode>, first_ip: usize, last_output: Intcode, ) -> (Intcode, ProgState) { let mut ip: usize = first_ip; loop { let mut st = None; { let opcode = mem[ip]; let is_imm = [ false, opcode / 100 % 10 != 0, opcode / 1000 % 10 != 0, opcode / 10000 % 10 != 0, ]; let ld_imm = |offset| mem[ip + offset as usize]; let ld = |offset| { if is_imm[offset] { ld_imm(offset) } else { mem[ld_imm(offset) as usize] } }; ip = match opcode_to_instr(opcode) { Add => { st = Some((ld(1) + ld(2), ld_imm(3))); ip + 4 } Mul => { st = Some((ld(1) * ld(2), ld_imm(3))); ip + 4 } In => { st = Some((input.next().unwrap(), ld_imm(1))); ip + 2 } Out => return (ld(1), Resume(ip + 2)), JmpIfTrue => { if ld(1) != 0 { ld(2) as usize } else { ip + 3 } } JmpIfFalse => { if ld(1) == 0 { ld(2) as usize } else { ip + 3 } } LessThan => { st = Some((if ld(1) < ld(2) { 1 } else { 0 }, ld_imm(3))); ip + 4 } Equals => { st = Some((if ld(1) == ld(2) { 1 } else { 0 }, ld_imm(3))); ip + 4 } Halt => return (last_output, Done), } } // All immutable borrows must go out of scope before it is OK to store // to 'mem', so this kind of simulates "write-back" step in a CPU... if let Some((val, addr)) = st { mem[addr as usize] = val; } } } fn amplifiers(program: &Vec<Intcode>, phases: &[Intcode; NUM_AMPS]) -> Intcode { let mut mems: Vec<Vec<Intcode>> = phases.iter().map(|_| program.clone()).collect(); let mut ips = [Resume(0); NUM_AMPS]; let mut outputs = [0; NUM_AMPS]; let mut result = 0; let mut first = true; 'terminated: loop { for (idx, &phase) in phases.iter().enumerate() { if let Resume(ip) = ips[idx] { let input = if first { vec![phase, result] } else { vec![result] }; let res = run(&mut mems[idx], &mut input.into_iter(), ip, outputs[idx]); result = res.0; ips[idx] = res.1; outputs[idx] = result; } else { break 'terminated; } } first = false; } result } fn run_with_phases(program: &Vec<Intcode>, phases: &mut [Intcode; NUM_AMPS]) -> Intcode { let mut thrusters_signal = Vec::new(); loop { thrusters_signal.push(amplifiers(program, phases)); if !phases.next_permutation() { break; } } thrusters_signal.into_iter().max().unwrap() } impl Solution for State { fn part1(&self) -> String { run_with_phases(&self.memory, &mut [0, 1, 2, 3, 4]).to_string() } fn part2(&self) -> String { run_with_phases(&self.memory, &mut [5, 6, 7, 8, 9]).to_string() } } pub fn solution(lines: Vec<&str>) -> Box<dyn Solution> { Box::new(State { memory: lines[0] .split(",") .map(|ic| ic.parse::<Intcode>().unwrap()) .collect(), }) }

Blev rÀtt i slutÀndan med min rejÀlt fula workaround for avsaknad av coroutines (vad mycket lÀttare detta varit i Go...)

Edit: fullstÀndigt projekt för alla dagar finns pÄ github. Körtiden för denna var ointeressant, 1 ms pÄ min 4 Är gammla jobblaptop.

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 ★
●

En Python-lösning för dag 7 med trÄdar och köer. Minimalt med state att hÄlla reda pÄ.

import itertools import Queue import threading import operator program = [3,8,1001,...,9,99] # No need to post this junk, get it from AOC args = { 0 : lambda m, pc : (m[m[pc + 1]], m[m[pc + 2]]), 1 : lambda m, pc : (m[pc + 1], m[m[pc + 2]]), 10 : lambda m, pc : (m[m[pc + 1]], m[pc + 2]), 11 : lambda m, pc : (m[pc + 1], m[pc + 2]) } op = [None, operator.add, operator.mul, None, None, None, None, operator.lt, operator.eq] def binop(pc, m, iq, oq): a1, a2 = args[m[pc] / 100](m, pc) m[m[pc + 3]] = op[m[pc] % 100](a1, a2) return pc + 4 def input(pc, m, iq, oq): m[m[pc + 1]] = iq.get() return pc + 2 def output(pc, m, iq, oq): a1, _ = args[m[pc] / 100](m, pc) oq.put(a1) return pc + 2 def condjump(pc, m, iq, oq): a1, a2 = args[m[pc] / 100](m, pc) return a2 if a1 == (m[pc] % 100 == 5) else pc + 3 instr = [None, binop, binop, input, output, condjump, condjump, binop, binop] def intcode(p, iq, oq): m = list(p) pc = 0 while m[pc] != 99: pc = instr[m[pc] % 100](pc, m, iq, oq) def amps(phase): # Set up the ring qs = [Queue.Queue(),Queue.Queue(),Queue.Queue(),Queue.Queue(),Queue.Queue()] ts = [] for i in range(5): ts.append(threading.Thread(target=intcode, args=(program, qs[i], qs[(i + 1) % 5]))) ts[i].start() qs[i].put(phase[i]) # Insert the Input value to Amp A qs[0].put(0) # Wait for Amp A to terminate ts[0].join() # We can now pick up the output valre from Amp E return qs[0].get() # Part one print max([amps(perm) for perm in itertools.permutations([0,1,2,3,4])]) # Part two print max([amps(perm) for perm in itertools.permutations([5,6,7,8,9])])

Dold text
PermalÀnk
Medlem ★
●

Dag: 5
SprÄk: Python
Del: 1&2

Varit en del annat sÄ nu ligger jag efter hÀr. Ska erkÀnna att bortsett frÄn dag 2 har jag nog aldrig ens sett den hÀr sortens problem förut, Àr som sagt rÀtt ny pÄ att koda. KÀnner en del frustration över att jag mÄste skriva sÄ mycket i mitt "switch-case" dÄ det Àr mycket som Àr nÀstan samma men jag fick inte ihop nÄgot generellt fall. Men ger det ett nytt försök nÀsta gÄng jag stöter pÄ datorn i frÄga.

#!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import sys def generate_input(): dir_path = os.path.dirname(os.path.realpath(__file__)) file_path = dir_path + "\\input.txt" with open(file_path) as inputfile: raw_instructions = [line.split(",") for line in inputfile.readlines()] instructions = [int(num) for num in raw_instructions[0]] return instructions def run_intcode(instructions, input_value): def opcode_1(term1, term2): total_sum = term1 + term2 return total_sum def opcode_2(factor1, factor2): product = factor1 * factor2 return product def parameter_modes(parameters): parameter_list = list(parameters) while len(parameter_list) < 3: parameter_list.insert(0,"0") parameter_list.reverse() return parameter_list pos = 0 opcode = None while opcode != "99": opcode = "".join(str(instructions[pos])[-2:]) if opcode == "01" or opcode == "1": print("Running OPC1") parameters = parameter_modes(str(instructions[pos])[:-2]) if parameters[0] == "0": term1 = instructions[instructions[pos + 1]] else: term1 = instructions[pos + 1] if parameters[1] == "0": term2 = instructions[instructions[pos + 2]] else: term2 = instructions[pos + 2] if parameters[2] == "0": output = instructions[pos + 3] else: output = pos + 3 instructions[output] = opcode_1(term1, term2) pos += 4 elif opcode == "02" or opcode == "2": print("Running OPC2") parameters = parameter_modes(str(instructions[pos])[:-2]) if parameters[0] == "0": factor1 = instructions[instructions[pos + 1]] else: factor1 = instructions[pos + 1] if parameters[1] == "0": factor2 = instructions[instructions[pos + 2]] else: factor2 = instructions[pos + 2] if parameters[2] == "0": output = instructions[pos + 3] else: output = pos + 3 instructions[output] = opcode_2(factor1, factor2) pos += 4 elif opcode == "03" or opcode == "3": print("Running OPC3") output = instructions[pos + 1] instructions[output] = input_value pos += 2 elif opcode == "04" or opcode == "4": print("Running OPC4") print(instructions[instructions[pos+1]]) pos += 2 elif opcode == "05" or opcode == "5": print("Running OPC5") parameters = parameter_modes(str(instructions[pos])[:-2]) if parameters[0] == "0": parameter1 = instructions[instructions[pos + 1]] else: parameter1 = instructions[pos + 1] if parameters[1] == "0": parameter2 = instructions[instructions[pos + 2]] else: parameter2 = instructions[pos + 2] if parameter1 != 0: pos = parameter2 else: pos += 3 elif opcode == "06" or opcode == "6": print("Running OPC6") parameters = parameter_modes(str(instructions[pos])[:-2]) if parameters[0] == "0": parameter1 = instructions[instructions[pos + 1]] else: parameter1 = instructions[pos + 1] if parameters[1] == "0": parameter2 = instructions[instructions[pos + 2]] else: parameter2 = instructions[pos + 2] if parameter1 == 0: pos = parameter2 else: pos += 3 elif opcode == "07" or opcode == "7": print("Running OPC7") parameters = parameter_modes(str(instructions[pos])[:-2]) if parameters[0] == "0": parameter1 = instructions[instructions[pos + 1]] else: parameter1 = instructions[pos + 1] if parameters[1] == "0": parameter2 = instructions[instructions[pos + 2]] else: parameter2 = instructions[pos + 2] if parameters[2] == "0": output = instructions[pos + 3] else: output = pos + 3 if parameter1 < parameter2: instructions[output] = 1 else: instructions[output] = 0 pos += 4 elif opcode == "08" or opcode == "8": print("Running OPC8") parameters = parameter_modes(str(instructions[pos])[:-2]) if parameters[0] == "0": parameter1 = instructions[instructions[pos + 1]] else: parameter1 = instructions[pos + 1] if parameters[1] == "0": parameter2 = instructions[instructions[pos + 2]] else: parameter2 = instructions[pos + 2] if parameters[2] == "0": output = instructions[pos + 3] else: output = pos + 3 if parameter1 == parameter2: instructions[output] = 1 else: instructions[output] = 0 pos += 4 elif opcode == "99": print("Quitting program") sys.exit() else: print("ERROR") raise ValueError(f"Something went horrible wrong at position {pos} with value {instructions[pos]}") return instructions def main(): instructions = generate_input() user_input = 5 #input("Which test would you like to run?: ") output = run_intcode(instructions, user_input) print(output[0]) if __name__ == "__main__": main()

Dold text
Visa signatur

PrimÀr: R9 3900X | ASUS X570-F Gaming | NH-D15 | 64GB@3200MHz | RTX 3080 10GB | Seasonic 850W | Fractal Define R6 |
Gamla bettan: i5 750@3.8GHz | 8GB | HD5770 | Corsair VS 550W | FD R2 |

PermalÀnk
Medlem
●
Skrivet av Yoshman:

Inte nöjd med dagens resultat. Kanske missförstÄtt nÄgot kring Rust, men kÀnns inte som coroutines Àr riktigt klart Àn (för den lösning jag tÀnkte pÄ ville inte kompilera p.g.a. "not a stable feature...").

use super::Solution; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use permutohedron::LexicalPermutation; use Instruction::*; use ProgState::*; type Intcode = i32; const NUM_AMPS: usize = 5; #[derive(Debug, FromPrimitive, PartialEq)] enum Instruction { Add = 1, Mul = 2, In = 3, Out = 4, JmpIfTrue = 5, JmpIfFalse = 6, LessThan = 7, Equals = 8, Halt = 99, } #[derive(Copy, Clone, Debug)] enum ProgState { Resume(usize), Done, } // State required to solve day 7 pub struct State { memory: Vec<Intcode>, } fn opcode_to_instr(opcode: Intcode) -> Instruction { FromPrimitive::from_i32(opcode % 100).expect("Invalid instruction") } fn run( mem: &mut Vec<Intcode>, input: &mut dyn Iterator<Item = Intcode>, first_ip: usize, last_output: Intcode, ) -> (Intcode, ProgState) { let mut ip: usize = first_ip; loop { let mut st = None; { let opcode = mem[ip]; let is_imm = [ false, opcode / 100 % 10 != 0, opcode / 1000 % 10 != 0, opcode / 10000 % 10 != 0, ]; let ld_imm = |offset| mem[ip + offset as usize]; let ld = |offset| { if is_imm[offset] { ld_imm(offset) } else { mem[ld_imm(offset) as usize] } }; ip = match opcode_to_instr(opcode) { Add => { st = Some((ld(1) + ld(2), ld_imm(3))); ip + 4 } Mul => { st = Some((ld(1) * ld(2), ld_imm(3))); ip + 4 } In => { st = Some((input.next().unwrap(), ld_imm(1))); ip + 2 } Out => return (ld(1), Resume(ip + 2)), JmpIfTrue => { if ld(1) != 0 { ld(2) as usize } else { ip + 3 } } JmpIfFalse => { if ld(1) == 0 { ld(2) as usize } else { ip + 3 } } LessThan => { st = Some((if ld(1) < ld(2) { 1 } else { 0 }, ld_imm(3))); ip + 4 } Equals => { st = Some((if ld(1) == ld(2) { 1 } else { 0 }, ld_imm(3))); ip + 4 } Halt => return (last_output, Done), } } // All immutable borrows must go out of scope before it is OK to store // to 'mem', so this kind of simulates "write-back" step in a CPU... if let Some((val, addr)) = st { mem[addr as usize] = val; } } } fn amplifiers(program: &Vec<Intcode>, phases: &[Intcode; NUM_AMPS]) -> Intcode { let mut mems: Vec<Vec<Intcode>> = phases.iter().map(|_| program.clone()).collect(); let mut ips = [Resume(0); NUM_AMPS]; let mut outputs = [0; NUM_AMPS]; let mut result = 0; let mut first = true; 'terminated: loop { for (idx, &phase) in phases.iter().enumerate() { if let Resume(ip) = ips[idx] { let input = if first { vec![phase, result] } else { vec![result] }; let res = run(&mut mems[idx], &mut input.into_iter(), ip, outputs[idx]); result = res.0; ips[idx] = res.1; outputs[idx] = result; } else { break 'terminated; } } first = false; } result } fn run_with_phases(program: &Vec<Intcode>, phases: &mut [Intcode; NUM_AMPS]) -> Intcode { let mut thrusters_signal = Vec::new(); loop { thrusters_signal.push(amplifiers(program, phases)); if !phases.next_permutation() { break; } } thrusters_signal.into_iter().max().unwrap() } impl Solution for State { fn part1(&self) -> String { run_with_phases(&self.memory, &mut [0, 1, 2, 3, 4]).to_string() } fn part2(&self) -> String { run_with_phases(&self.memory, &mut [5, 6, 7, 8, 9]).to_string() } } pub fn solution(lines: Vec<&str>) -> Box<dyn Solution> { Box::new(State { memory: lines[0] .split(",") .map(|ic| ic.parse::<Intcode>().unwrap()) .collect(), }) }

Blev rÀtt i slutÀndan med min rejÀlt fula workaround for avsaknad av coroutines (vad mycket lÀttare detta varit i Go...)

Edit: fullstÀndigt projekt för alla dagar finns pÄ github. Körtiden för denna var ointeressant, 1 ms pÄ min 4 Är gammla jobblaptop.

Om du vill ha en annan metod som ocksÄ Àr ganska analog goroutines sÄ kan du anvÀnda vanliga trÄdar och kanaler. De Àr ju inte lika lÀttviktiga som coroutines förstÄs, men inte sÄ tunga att det hade spelat nÄgon praktisk roll för ett sÄnt hÀr problem.

Visa signatur

Arbets- / Spelstation: Arch Linux - Ryzen 5 3600 - RX 7900 XT - 32G DDR4
Server: Arch Linux - Core i5-10400F - 16G DDR4

PermalÀnk
Medlem
●

Dag: 7
SprÄk: Haskell

Najs, fick tillfÀlle att utnyttja Haskells laziness för att lösa part 2 med en cyklisk definition. Det Àr inte varje dag!

För er som inte vet men Àr nyfikna sÄ Àr en cyklisk definition till exempel följande definition av den oÀndliga listan av naturliga tal [0, 1, ...].

> nats = 0 : map (+ 1) nats > take 10 nats [0,1,2,3,4,5,6,7,8,9]

Haskells laziness gör att hela nats inte berÀknas pÄ en gÄng sÄ fort den anvÀnds, utan bara de element som behövs berÀknas. Detta möjliggör cykler utan att man fastnar i en evighetsloop.

Jag blev vÀldigt nöjd med min lösning av part 2, dÀr jag kunde anvÀnda en lat, cyklisk definition av förstÀrkar-systemet för att representera feedback-loopen. Följande Àr det relevanta stycket:

amp ampPgm phaseSettings = let ampStage s inps = run (s : inps) ampPgm outs = foldl (&) (0 : init outs) (map ampStage phaseSettings) in last outs

Inte ofta jag fÄr tillfÀlle för sÄnt. Ofta gÄr man direkt till strikta funktioner och datastrukturer i Haskell för att förbÀttra prestanda, och dÄ Àr ju cykler av detta slaget inte möjliga.

{-# LANGUAGE LambdaCase, TemplateHaskell, TypeApplications #-} module Day7 (part1, part2) where import Control.Monad.State import Control.Monad.Writer import Control.Applicative import Data.Function import Data.List.Split import Data.List import Lens.Micro.Platform (makeLenses, use, to, modifying, (<<%=), assign) import Data.Sequence (Seq) import Data.Composition import qualified Data.Sequence as Seq newtype Addr = Addr Int deriving (Ord, Eq) type Pc = Int type Mem = Seq Int data St = St { _pc :: Pc, _inp :: [Int], _mem :: Mem } makeLenses ''St type Eval a = StateT St (Writer [Int]) a part1 :: IO Int part1 = fmap (\pgm -> maximum (map (amp pgm) (permutations [0 .. 4]))) (fmap parse readInput) where amp ampPgm = foldl' (&) 0 . map (\s -> \inp -> head (run [s, inp] ampPgm)) part2 :: IO Int part2 = fmap (\pgm -> maximum (map (amp pgm) (permutations [5 .. 9]))) (fmap parse readInput) where amp ampPgm phaseSettings = let ampStage s inps = run (s : inps) ampPgm outs = foldl (&) (0 : init outs) (map ampStage phaseSettings) in last outs readInput :: IO String readInput = readFile "inputs/day-7" parse :: String -> Mem parse = Seq.fromList . fmap read . splitOn "," run :: [Int] -> Mem -> [Int] run = execWriter . evalStateT eval .* St 0 eval :: Eval () eval = step >>= \case True -> pure () False -> eval step :: Eval Bool step = do (opcode, modes) <- nextInstr let binop' = binop (modes !! 0) (modes !! 1) let jmpIf' = jmpIf (modes !! 0) (modes !! 1) case opcode of 1 -> binop' (+) 2 -> binop' (*) 3 -> input 4 -> output (modes !! 0) 5 -> jmpIf' (/= 0) 6 -> jmpIf' (== 0) 7 -> binop' (fromEnum .* (<)) 8 -> binop' (fromEnum .* (==)) 99 -> pure () _ -> error "Undefined opcode" pure (if opcode == 99 then True else False) where nextInstr = fmap (\x -> (extractOpcode x, extractModes x)) next extractOpcode x = mod x 100 extractModes x = map (\n -> mod (div x (10 ^ n)) 10) [2 :: Int ..] next = load . Addr =<< (pc <<%= (+ 1)) binop amode bmode f = do v <- liftA2 f (getArg amode) (getArg bmode) dst <- nextAddr store dst v input = do i <- fmap head (inp <<%= tail) dst <- nextAddr store dst i output mode = tell . pure =<< getArg mode jmpIf amode bmode pred = do (a, b) <- liftA2 (,) (getArg amode) (getArg bmode) when (pred a) (assign pc b) getArg = \case 0 -> load =<< nextAddr -- Address mode 1 -> next -- Immediate mode _ -> error "Undefined mode" nextAddr = fmap Addr next store :: Addr -> Int -> Eval () store (Addr i) = modifying mem . Seq.update i load :: Addr -> Eval Int load (Addr i) = use (mem . to (flip Seq.index i))

Dold text
Visa signatur

Arbets- / Spelstation: Arch Linux - Ryzen 5 3600 - RX 7900 XT - 32G DDR4
Server: Arch Linux - Core i5-10400F - 16G DDR4

PermalÀnk
Medlem ★
●

Dag 7
Uppgift 1&2
SprÄk C#
Kommentar: Sjukt svÄrt för mig... pinsamt. Ja fÀrdiga koden var i alla fall knappt ens mÀtbar, fick 40 respektive 60 ms. Lite debugskit jag inte orkar rensa Àr kvar... Som sagt, skamvrÄn för mig. Grymt imponerad av alla andra som lyckas i alla dessa sprÄk med tajta lösningar.

private void button7_Click(object sender, EventArgs e) { System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew(); Dictionary<int, int[]> sequenceList; if (this.numSubTask.Value==2) { sequenceList = GetSequenceList("56789"); } else { sequenceList = GetSequenceList("01234"); } Dictionary<string, int> stringRef = new Dictionary<string, int>(); foreach (KeyValuePair<int,int[]> item in sequenceList) { string seqStr = String.Empty; for (int i = 0; i < item.Value.Length; i++) { seqStr = seqStr + item.Value[i].ToString(); } stringRef.Add(seqStr, item.Key); } int maxOutPut = 0; int maxSequenceId = -1; for (int i = 0; i < sequenceList.Count; i++) { int testThrust = GetThrusterValue(sequenceList[i]); if (testThrust>maxOutPut) { maxSequenceId = i; maxOutPut = testThrust; } } txtAnswer.Text =string.Join(",", sequenceList[maxSequenceId]) + "€" + maxOutPut.ToString(); watch.Stop(); Int64 elapsedMs = watch.ElapsedMilliseconds; label1.Text = elapsedMs.ToString(); } private int GetThrusterValue(int[] sequence) { int thrust = 0; //int lastThrust = 0; int i = 0; bool keepGoing= true; IntCode[] amplifier = { new IntCode(), new IntCode(), new IntCode(), new IntCode(), new IntCode() }; while (keepGoing) { int[] inputs = new int[2]; inputs[0] = sequence[i]; inputs[1] = thrust; //IntCode computer = new IntCode(this.txtInput.Text, inputs); if (!amplifier[i].isInitialized) { amplifier[i].Init(this.txtInput.Text, inputs); } int? outputs = amplifier[i].Compute(); //int resCount = outputs.Count; if (outputs==null) { keepGoing=false; } else { thrust = (int)outputs; i++; if (i>(sequence.Length-1)) { i = 0; } if (!amplifier[i].isInitialized) { inputs[0] = sequence[i]; inputs[1] = thrust; amplifier[i].Init(this.txtInput.Text, inputs); } else { amplifier[i].AddInput(thrust); } } } return thrust; } private Dictionary<int,int[]> GetSequenceList(string phases ="01234") { Dictionary<int, int[]> combos = new Dictionary<int, int[]>(); List<int> baseList = new List<int>(); int[] phase = new int[phases.Length]; for (int i = 0; i < phases.Length; i++) { phase[i] = ToSafeInt(phases.Substring(i,1)); } for (int i = 0; i < 5; i++) { baseList.Add(i); } int sequenceNumber = 0; for (int i1 = 0; i1 < 5; i1++) { List<int> val2List = baseList.ToList(); val2List.Remove(i1); for (int i2 = 0; i2 < 4; i2++) { int i2val = val2List.ElementAt(i2); List<int> val3List = val2List.ToList(); val3List.Remove(i2val); for (int i3 = 0; i3 < 3; i3++) { int i3val = val3List.ElementAt(i3); List<int> val4List = val3List.ToList(); val4List.Remove(i3val); for (int i4 = 0; i4 < 2; i4++) { int i4val = val4List.ElementAt(i4); List<int> val5List = val4List.ToList(); val5List.Remove(i4val); int i5val = val5List.ElementAt(0); int[] curSeq = new int[5]; curSeq[0] = phase[i1]; curSeq[1] = phase[i2val]; curSeq[2] = phase[i3val]; curSeq[3] = phase[i4val]; curSeq[4] = phase[i5val]; combos.Add(sequenceNumber, curSeq); sequenceNumber++; } } } } return combos; } public class IntCode { private bool endedCorrectly = false; public bool EndedCorrectly { get { return endedCorrectly; } } public bool isInitialized = false; int currentPosition = 0; int inputstep = 0; private string _program; private Dictionary<OpCode, int> parameterCount = new Dictionary<OpCode, int>(); private Dictionary<int, int> _outputs = new Dictionary<int, int>(); public int[] data; private Dictionary<int,int> _inputs = new Dictionary<int, int>(); public enum OpCode { Add=1, Mul=2, In=3, Out=4, JiT=5, JiF=6, Les=7, Eq=8, End=99 } public enum ParamMode { Ref=0, Val=1 } public void AddInput(int input) { int nextInpPos = _inputs.Count; _inputs.Add(nextInpPos, input); } public IntCode(string program, int? input=null) { _program = program; if (input!=null) { AddInput((int)input); } Initialize(); } public IntCode() { } public void Init(string program, int[] inputs = null) { _program = program; if (inputs != null) { foreach (int item in inputs) { AddInput(item); } } Initialize(); } private void Initialize() { parameterCount.Clear(); parameterCount.Add(OpCode.Add, 3); parameterCount.Add(OpCode.Mul, 3); parameterCount.Add(OpCode.In, 1); parameterCount.Add(OpCode.Out, 1); parameterCount.Add(OpCode.JiT, 2); parameterCount.Add(OpCode.JiF, 2); parameterCount.Add((OpCode.Les), 3); parameterCount.Add(OpCode.Eq, 3); parameterCount.Add(OpCode.End, 0); data = GetSafeIntArray(_program); isInitialized = true; } private int[] GetSafeIntArray(string input) { string[] strArr = input.Split(','); int[] intArr = new int[strArr.Length]; for (int i = 0; i < strArr.Length; i++) { intArr[i] = ToSafeInt(strArr[i]); } return intArr; } private static int ToSafeInt(string val, int error = -1) { int test; bool isint = int.TryParse(val, out test); if (isint) { return test; } return error; } public static ParamMode[] getParameterModes(string modes) { ParamMode[] pModes = new ParamMode[modes.Length]; for (int i = 0; i < modes.Length; i++) { pModes[modes.Length - i - 1] = (ParamMode)ToSafeInt(modes.Substring(i, 1)); } return pModes; } public int? Compute() { if (!isInitialized) { throw new Exception("Computer is not initialized!"); } int? lastOutPut = null; int posCount = data.Length; bool noExit = true; //string lastOutPut = String.Empty; int outputstep = 0; _outputs.Clear(); while (currentPosition < posCount && noExit) { string posCode = data[currentPosition].ToString("D5"); OpCode opCode = (OpCode)ToSafeInt(posCode.Substring(3, 2)); ParamMode[] parameterMode = getParameterModes(posCode.Substring(0, 3)); int paramCount = parameterCount[opCode]; if (opCode==OpCode.End) { endedCorrectly = true; noExit = false; return lastOutPut; } int[] parameters=new int[paramCount]; int[] values = new int[paramCount]; for (int i = 0; i < paramCount; i++) { parameters[i] = data[currentPosition + 1 + i]; if (parameterMode[i]==ParamMode.Ref) { values[i] = data[parameters[i]]; } else { values[i] = parameters[i]; } } switch (opCode) { case OpCode.Add: data[parameters[2]] = values[0] + values[1]; currentPosition = currentPosition + 1 + paramCount; break; case OpCode.Mul: data[parameters[2]] = values[0] * values[1]; currentPosition = currentPosition + 1 + paramCount; break; case OpCode.In: data[parameters[0]] = _inputs[inputstep]; inputstep++; currentPosition = currentPosition + 1 + paramCount; break; case OpCode.Out: _outputs.Add(outputstep, data[parameters[0]]); outputstep++; currentPosition = currentPosition + 1 + paramCount; return values[0]; case OpCode.JiT: if (values[0]!=0) { currentPosition = values[1]; } else { currentPosition = currentPosition + 1 + paramCount; } break; case OpCode.JiF: if (values[0] == 0) { currentPosition = values[1]; } else { currentPosition = currentPosition + 1 + paramCount; } break; case OpCode.Les: if (values[0]<values[1]) { data[parameters[2]] = 1; } else { data[parameters[2]] = 0; } currentPosition = currentPosition + 1 + paramCount; break; case OpCode.Eq: if (values[0] == values[1]) { data[parameters[2]] = 1; } else { data[parameters[2]] = 0; } currentPosition = currentPosition + 1 + paramCount; break; case OpCode.End: currentPosition = currentPosition + 1; endedCorrectly = true; noExit = false; break; default: break; } if (!nextIsValid(data[currentPosition])) { throw new Exception("Hur kom vi hit?"); } } if (endedCorrectly) { return lastOutPut; } else { return null; } } private bool nextIsValid(int nextInstruction) { string posCode = data[currentPosition].ToString("D5"); OpCode opCode = (OpCode)ToSafeInt(posCode.Substring(3, 2)); return parameterCount.ContainsKey(opCode); } }

Dold text
PermalÀnk
Medlem ★
●
Skrivet av eurythmech:

Tycker inte körtiderna Àr sÀrskilt intressanta Àn sÄ lÀnge. Men det blir vÀl vÀrre lÀngre fram.

❯ pytest --durations=0 ================================================================================================== test session starts ================================================================================================== platform win32 -- Python 3.7.3, pytest-5.3.1, py-1.8.0, pluggy-0.13.1 rootdir: C:\Users\chris\source\repos\advent_of_code_2019\estomagordo-python3 collected 14 items test_correctness.py .............. [100%] ================================================================================================ slowest test durations ================================================================================================= 0.64s call test_correctness.py::test_4b 0.56s call test_correctness.py::test_4a 0.18s call test_correctness.py::test_3a 0.17s call test_correctness.py::test_3b 0.09s call test_correctness.py::test_2b 0.04s call test_correctness.py::test_7b 0.02s call test_correctness.py::test_6a 0.01s call test_correctness.py::test_7a (0.00 durations hidden. Use -vv to show these durations.)

Nej kanske inte för alla men jag som kĂ€mpar för att ens klara uppgifterna skulle det vara kul att se hur lĂ„ngt jag har kvar i prestandaperspektiv och som sagt kul att veta. Älskar siffror.

PermalÀnk
Datavetare ★
●

Go - dag 7

Skrivet av Bryal:

Om du vill ha en annan metod som ocksÄ Àr ganska analog goroutines sÄ kan du anvÀnda vanliga trÄdar och kanaler. De Àr ju inte lika lÀttviktiga som coroutines förstÄs, men inte sÄ tunga att det hade spelat nÄgon praktisk roll för ett sÄnt hÀr problem.

Tack för den informationen! Kollade in channels och trÄdar, hade definitivt fungerat!

Är som sagt nybörjare pĂ„ Rust (men tror det kan vara framtiden OS sprĂ„k, sĂ„ vill lĂ€ra mig det!!!), har inte börjat titta pĂ„ saker som trĂ„dar Ă€n. Det ihop med att jag hade en idĂ© gjorde att tanken hamnade i ett hörn

Var nÄgot likt detta jag filade pÄ initialt

package main import ( "fmt" ) type Memory []int const NUM_AMPLIFIERS = 5 const ( Add = iota + 1 Mul In Out JmpIfTrue JmpIfFalse LessThan Equal Halt = 99 ) func run(mem Memory, input <-chan int, output chan<- int) { defer close(output) ip := 0 ld_imm := func(addr int) int { return mem[addr] } for { opcode := mem[ip] is_imm := []bool{opcode/100%10 != 0, opcode/1000%10 != 0} ld := func(offset int) int { v := ld_imm(offset + ip) if !is_imm[offset-1] { v = mem[v] } return v } st := func(offset, val int) { mem[ld_imm(offset+ip)] = val } switch opcode % 100 { case Add: st(3, ld(1)+ld(2)) ip += 4 case Mul: st(3, ld(1)*ld(2)) ip += 4 case In: st(1, <-input) ip += 2 case Out: output <- ld(1) ip += 2 case JmpIfFalse: if ld(1) == 0 { ip = ld(2) } else { ip += 3 } case JmpIfTrue: if ld(1) != 0 { ip = ld(2) } else { ip += 3 } case LessThan: if ld(1) < ld(2) { st(3, 1) } else { st(3, 0) } ip += 4 case Equal: if ld(1) == ld(2) { st(3, 1) } else { st(3, 0) } ip += 4 case Halt: return default: panic("Invalid instruction") } } } func amplifiers(program Memory, phases []int) (chan<- int, <-chan int) { var chs [NUM_AMPLIFIERS + 1]chan int for i := 0; i <= NUM_AMPLIFIERS; i++ { chs[i] = make(chan int, 1) } for i := 0; i < NUM_AMPLIFIERS; i++ { mem := make(Memory, len(program)) copy(mem, program) go run(mem, chs[i], chs[i+1]) chs[i] <- phases[i] } return chs[0], chs[NUM_AMPLIFIERS] } func thrustWithPhases(prog Memory, phases []int) int { tx, rx := amplifiers(prog, phases) tx <- 0 final_result := 0 // Loop while the amplifiers has not halted for result := range rx { tx <- result final_result = result } return final_result } func maxThrust(prog Memory, phases []int) (max int) { ch := make(chan int) go func() { defer close(ch) Perm(phases, func(phasesPerm []int) { ch <- thrustWithPhases(prog, phasesPerm) }) }() max = <-ch for thrust := range ch { if max < thrust { max = thrust } } return } func main() { prog := loadProgram("input.txt") fmt.Println(maxThrust(prog, []int{0, 1, 2, 3, 4})) fmt.Println(maxThrust(prog, []int{5, 6, 7, 8, 9})) }

HÀr löst med Go's goroutines och channels

Edit: ovan tar 4 ms att köra pÄ en i7-8559U (förra Ärets NUC)

Visa signatur

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

PermalÀnk
●
Skrivet av Mordekai:

Nej kanske inte för alla men jag som kĂ€mpar för att ens klara uppgifterna skulle det vara kul att se hur lĂ„ngt jag har kvar i prestandaperspektiv och som sagt kul att veta. Älskar siffror.

SÄhÀr ser det ut i Kotlin för mig Àn sÄ lÀnge (pÄ en MacBook Pro frÄn 2013).

1: 7 ms
2: 58 ms
3: 199 ms
4: 4 ms
5: 1 ms
6: 756 ms
7: 9 ms

Jag har haft samma tid pÄ del 1 och 2 av varje uppgift Àn sÄ lÀnge. Har inte försökt skala ner nÄgra tider alls men gissar att t.ex. 6an blev mycket lÄngsammare för jag körde immutable collections just den dagen.

Visa signatur

"Knowledge amplification. What he learns, we all learn. What he knows, we all benefit from."

PermalÀnk
Medlem ★
●

Har spenderat för mycket tid pÄ att göra dag 7 uppgift 2 multitrÄdad, gick frÄn 50 ms för enkeltrÄdad till 700 ms multitrÄdad. Inga locks men Join. Gjorde en trÄd per kombination (120 trÄdar).
C#
Kopierade input till samtliga trÄdar...
Verkar inte vara det, mÄste vara trÄdhanteringen som har sÄ mycket overhead.

PermalÀnk
Medlem
●
Skrivet av Mordekai:

Har spenderat för mycket tid pÄ att göra dag 7 uppgift 2 multitrÄdad, gick frÄn 50 ms för enkeltrÄdad till 700 ms multitrÄdad. Inga locks men Join. Gjorde en trÄd per kombination (120 trÄdar).
C#
Kopierade input till samtliga trÄdar...
Verkar inte vara det, mÄste vara trÄdhanteringen som har sÄ mycket overhead.

Om det Àr fullblÄsta OS-trÄdar du skapar sÄ har de indeed en hel del overhead. Skapa istÀllet lika mÄnga trÄdar i programmet som du har trÄdar i processorn, sÄ kan du eliminera mycket overhead frÄn frÀmst kontextbyte.

Visa signatur

Arbets- / Spelstation: Arch Linux - Ryzen 5 3600 - RX 7900 XT - 32G DDR4
Server: Arch Linux - Core i5-10400F - 16G DDR4

PermalÀnk
Medlem ★
●
Skrivet av KentRoyal:

SÄhÀr ser det ut i Kotlin för mig Àn sÄ lÀnge (pÄ en MacBook Pro frÄn 2013).

1: 7 ms
2: 58 ms
3: 199 ms
4: 4 ms
5: 1 ms
6: 756 ms
7: 9 ms

Jag har haft samma tid pÄ del 1 och 2 av varje uppgift Àn sÄ lÀnge. Har inte försökt skala ner nÄgra tider alls men gissar att t.ex. 6an blev mycket lÄngsammare för jag körde immutable collections just den dagen.

FÄr detta i C pÄ en 3900X, en del debugutskrifter kvar pÄ vissa som tar lite tid.

1: 1 resp 2 ms
2: 1 resp 32 ms
3: 11970 resp 14387 ms (mÄste anvÀnt en suboptimal algoritm hÀr)
4: 1 resp 1 ms
5: 1 resp 1 ms
6: 3 resp 5 ms
7: 2 resp 18 ms

PermalÀnk
Medlem ★
●
Skrivet av KentRoyal:

SÄhÀr ser det ut i Kotlin för mig Àn sÄ lÀnge (pÄ en MacBook Pro frÄn 2013).

1: 7 ms
2: 58 ms
3: 199 ms
4: 4 ms
5: 1 ms
6: 756 ms
7: 9 ms

Jag har haft samma tid pÄ del 1 och 2 av varje uppgift Àn sÄ lÀnge. Har inte försökt skala ner nÄgra tider alls men gissar att t.ex. 6an blev mycket lÄngsammare för jag körde immutable collections just den dagen.

Tack Kent!
1: 0ms : 0ms
2: 2ms : 2ms
3: 230ms : 350ms
4: 350ms : 360ms
5: 0ms : 0ms
6: 160ms : 160ms
7: 40ms : 50ms

SÄ jag var sÀmst pÄ fyran relativt, trodde min IntCode computer blivit riktigt snabb men jÀmfört med din Àr den ju rena skördetröskan.

Det hÀr Àr ju sjukt kul!

PermalÀnk
Medlem ★
●
Skrivet av SAFA:

FÄr detta i C pÄ en 3900X, en del debugutskrifter kvar pÄ vissa som tar lite tid.

1: 1 resp 2 ms
2: 1 resp 32 ms
3: 11970 resp 14387 ms (mÄste anvÀnt en suboptimal algoritm hÀr)
4: 1 resp 1 ms
5: 1 resp 1 ms
6: 3 resp 5 ms
7: 2 resp 18 ms

Nice! C regerar.