Du må være registrert og logget inn for å kunne legge ut innlegg på freak.no
X
LOGG INN
... eller du kan registrere deg nå
Dette nettstedet er avhengig av annonseinntekter for å holde driften og videre utvikling igang. Vi liker ikke reklame heller, men alternativene er ikke mange. Vær snill å vurder å slå av annonseblokkering, eller å abonnere på en reklamefri utgave av nettstedet.
  21 5028
Ho-ho!

I år som i fjor, så har vi flere julekalendere og programmeringsnøtter å kose oss med i adventstida.


Advent of Code:
Advent of Code is a series of small programming puzzles for a variety of skill levels. They are self-contained and are just as appropriate for an expert who wants to stay sharp as they are for a beginner who is just learning to code. Each puzzle calls upon different skills and has two parts that build on a theme.
Vis hele sitatet...

Knowit Julekalender
Kodekalenderen er kalenderen for deg som er glad i programmering. Hver luke er en oppgave som løses best ved hjelp av kode.

Lukene varierer i vanskelighetsgrad og utforming, men felles for alle er at koden til løsningen din skal resultere i et svar på en linje som systemet kan sjekke om er korrekt.
Vis hele sitatet...

I denne tråden kan dere både dele deres egne løsninger, og spørre om hint dersom du står fast selv. Enten du vil skryte av en rask kjøretid, eller mangler den siste lille biten for å få løsningen din i mål -- dette er din tråd!


OBSOBSOBSOBSOBS

Kjøreregler:
  • Løsninger skal postes med spoilertags!
    SPOILER ALERT! Vis spoiler

    Kode

    Slik som dette.
  • Knowit-kalenderen har premier, så post derfor ikke løsningen din før dagen etter.


Håper å få se mange fiffige løsninger i et variert utvalg av programmeringsspråk!


PS: Si gjerne i fra i denne tråden dersom du vet om flere programmeringsjulekalendere av dette slaget!
React-julekalender laget av en kollega: https://react.christmas/
Her er mine løsninger på AdventOfCode luke 1 i JS:

SPOILER ALERT! Vis spoiler

Kode

function part1(data) {
  let sum = 0;

  let previous = data[data.length - 1];
  for (let i = 0; i < data.length; i++) {
    if (previous == data[i]) {
      sum = sum + parseInt(data[i]);
    }
    previous = data[i];
  }

  return sum;
}

function part2(data) {
  const halfWay = parseInt(data.length / 2);
  let sum = 0;
  let prevIndex = halfWay;

  let previous = data[prevIndex];
  for (let i = 0; i < data.length; i++) {
    if (previous == data[i]) {
      sum = sum + parseInt(data[i]);
    }
    
    if (prevIndex < data.length - 1) {
      prevIndex += 1;
    }
    else {
      prevIndex = 0;
    }
    previous = data[prevIndex];
  }

  return sum;
}
nso
popålol
nso's Avatar
Administrator
AdventOfCode dag 1 i javascript.

SPOILER ALERT! Vis spoiler

Innså etter å ha laget to algoritmer at de var såpass like at det var like greit å slå dem sammen siden det uansett bare var å steppe igjennom en streng med et forhåndsdefinert offset. Også litt gøy at jeg tror dette er første gang noen sinne at jeg har sett behov for å definere og inkrementere flere variabler i for-løkken. Alt i alt en relativt enkel men artig oppgave.

Kode

function day1(str, offset, multiplier) {
  let result = 0;

  for (let i = 0, j = offset; i < str.length - offset; i++, j++)
    result += parseInt(str[i] == str[j < str.length ? j : j - str.length] ? str[i] : 0) * multiplier;
 
  return result;
}

let str = "....";
let part1 = day1(str, 1, 1);
let part2 = day1(str, str.length / 2, 2);
Sist endret av nso; 2. desember 2017 kl. 01:55.
Gøy å se løsninger! Her er min i Python for AoC luke 1:

SPOILER ALERT! Vis spoiler
Jeg la også merke til at jeg fikk veldig lik kode, og slo dem sammen for å slippe å skrive samme kode flere ganger. Looper bare gjennom alle sifrene (bortsett fra siste siffer) og sjekker om a) sifferet er likt neste neste siffer, og b) om sifferet er lik sifferet som har L/2 høyere indeks, der L er lengden av hele driten. Hvis de er like så øker jeg de respektive sum-variablene. Til slutt en spesialsjekk for å sjekke om første og siste tall er likt. Slik ble det:

Kode

with open('input.txt') as f:
	num = f.readline()

tot1, tot2 = 0, 0
for i in range(len(num)-1):
	if num[i] == num[i+1]:
		tot1 += int(num[i])
	if i < len(num)/2 and num[i] == num[i+len(num)//2]:
		tot2 += 2*int(num[i])
if num[0] == num[-1]:
	tot1 += int(num[0])
print('1st:', tot1)
print('2nd:', tot2)
[Python]AoC luke 2:
SPOILER ALERT! Vis spoiler

Kode

with open('2_input.txt') as f:
    lst = [[int(i) for i in line.split()] for line in f]

print(sum(max(line) - min(line) for line in lst))
Sitat av snippsat Vis innlegg
[Python]AoC luke 2:
SPOILER ALERT! Vis spoiler

Kode

with open('2_input.txt') as f:
    lst = [[int(i) for i in line.split()] for line in f]

print(sum(max(line) - min(line) for line in lst))
Vis hele sitatet...
Pent. Hva med del 2? Lurer på om det finnes noen smarte triks.
Sist endret av Realist1; 2. desember 2017 kl. 13:25.
Sitat av Realist1 Vis innlegg
Pent. Hva med del 2? Lurer på om det finnes noen smarte triks.
Vis hele sitatet...
Jeg så ikke del 2 i farta
Må vel teste all kombinasjoner i listen,så da kan itertools combinations brukes.
[Python]Aoc luke 2:
SPOILER ALERT! Vis spoiler

Kode

from itertools import combinations

with open('2_input.txt') as f:
    lst = [[int(i) for i in line.split()] for line in f]

ans_1 = sum(max(line) - min(line) for line in lst)
ans_2 = sum(x//y for line in lst for y,x in combinations(sorted(line),2) if x%y == 0)
print(ans_1)
print(ans_2)
Akkurat ja. Veldig bra.

Tror ikke jeg skal poste min løsning i dag nei.
Rakk ikke nerde meg i går, men ingenting er bedre for å komme seg til hektene etter gårsdagens julebord enn å børste støv av Haskell:

AoC 1
SPOILER ALERT! Vis spoiler

Kode

import Data.Char
main = print (solveCaptcha2 "823...")

solveCaptcha1 s = captchaSum 1 (readCaptcha s)
solveCaptcha2 s = let xs = readCaptcha s
                  in captchaSum (div (length xs)  2) xs

readCaptcha = map digitToInt
captchaSum shift xs = sum [x | (x,y) <- zip xs (drop shift (cycle xs)), x == y]


AoC 2
SPOILER ALERT! Vis spoiler

Kode

main = do
    textBlob <- readFile "dec02.txt"
    let ls = lines textBlob
    print(solve2 ls)

solve = checkSum . parseSheet
solve2 = sumEvenDivs . parseSheet

parseSheet::[String]-> [[Int]]
parseSheet = map parseLine

parseLine::String->[Int]
parseLine line = [read cell | cell <- words line]

checkSum::[[Int]] -> Int
checkSum = sum . map (\xs -> (maximum xs) - (minimum xs))

sumEvenDivs::[[Int]]->Int
sumEvenDivs = sum . map evenDivs

evenDivs::[Int]->Int
evenDivs xs = head [ x `div` y | x <- xs, y <- xs, x /= y && x `mod` y == 0]
NOOOOOOOOOOOOOOOOOO-
robhol's Avatar
Løsningene mine for de to første dagene i AoC. Knowit blir for omfattende til at jeg gidder.

Språket er C# og LINQ er min drug of choice. Jeg har ikke et problem, jeg lover.

Dag 1: https://gist.github.com/robhol/f02d6...3caade1d6e5cc8

Dag 2: https://gist.github.com/robhol/57db5...7ebf9ed3f15235
Advent of Code dag 3 kan løses uten kode, om man gjenkjenner det matematiske bak oppgaven.

SPOILER ALERT! Vis spoiler

Del 1 er Ulam's Spiral. Kan lett observere at diagonalene ned mot høyre er kvadrater av oddetall. Da er det bare å ekstrapolere denne diagonalen nedover til man er i nærheten av tallet sitt, og så telle fram eller tilbake til det.

Del 2 er OEIS A141481 og alle løsningene er her: http://oeis.org/A141481/b141481.txt


Min løsning med kode for del 1 er som følger: https://pastebin.com/Ftda46VD
Sist endret av Dyret; 4. desember 2017 kl. 15:57.
[Python]AoC luke 4:
SPOILER ALERT! Vis spoiler

Kode

# Part 1
from collections import Counter

count = 0
with open('4.txt') as f:
    for line in f:
        if Counter(line.split()).most_common(1)[0][-1] == 1:
            count += 1

print(count)

Kode

# Part 2
from itertools import combinations

anagrams = 0
with open('4.txt') as f:
    for line_nr,line in enumerate(f, 1):
        for a, b in combinations(line.split(), 2):
            if sorted(a) == sorted(b):
                anagrams += 1
                break

print(line_nr - anagrams)
Sist endret av snippsat; 4. desember 2017 kl. 14:32.
[Python3]AoC luke 4:
SPOILER ALERT! Vis spoiler

Kode

passphrases = [p.rstrip() for p in open("4.txt").readlines()]

# Part 1
valid = 0
for passphrase in passphrases:
    words = passphrase.split()
    if len(set(words)) == len(words):
        valid += 1
print("Part 1: {}".format(valid))

# Part 2
valid = 0
for passphrase in passphrases:
    words = [''.join(e) for e in map(sorted, passphrase.split())]
    if len(set(words)) == len(words):
        valid += 1
print("Part 2: {}".format(valid))
I del 1 så legger jeg alle ordene i et set-objekt, som kun kan inneholde unike objekter. Om det er like mange objekter i settet som i listen med ord, må alle ordene være unike.

I del 2 så gjør jeg det samme, men sorterer hvert ord først. To ord er anagrammer (eller like) om de er like etter sortering. Dette kravet er derfor sterkere enn det i del 1, og jeg trenger derfor ikke å sjekke at de oppfyller del 1 også.
Sist endret av Dyret; 4. desember 2017 kl. 15:19.
nok en [Py3]AoC luke 4:
SPOILER ALERT! Vis spoiler

Kode

# første del
with open('day4') as file:
    print(sum([1 for line in file if len(set(line.split())) == len(line.split())]))

# andre del
with open('day4') as file:
    print(sum([1 for line in file if len(line.split()) == len(set([''.join(sorted(l)) for l in line.split()]))]))

Stort sett det samme som Dyret, men færre linjer, og mindre leselig
AoC 4. desember i Haskell (kun del 2)

SPOILER ALERT! Vis spoiler

Brukte som de før meg også set. Men kortslutter med en gang jeg finner en duplikat i stedet for å telle om de er like lange.

Kode

import Data.Bool
import Data.List
import qualified Data.Set as Set

main = do
    textBlob <- readFile "dec04.txt"
    let ls = lines textBlob
    print(solve ls)

solve ls = length $ filter (\x -> x) $ map isValidPassphrase ls

isValidPassphrase::String -> Bool
isValidPassphrase phrase = let sortedWords = map sort (words phrase)
    in not (anyDuplicates Set.empty sortedWords)    

anyDuplicates :: Set.Set String -> [String] -> Bool
anyDuplicates used [] = False
anyDuplicates used (w:ws) = isMember || (anyDuplicates (Set.insert w used) ws)
    where isMember = Set.member w used
Min løsning for AoC4 i JS:

SPOILER ALERT! Vis spoiler

Siden oppgavene er relativt like slang jeg på argument 2 for å sjekke på en strengere måte.

Kode

function is_valid(input, sorted) {
  const words = input.split(' ');
  const uniques = [];
  words.forEach((word) => {
    if (sorted) {
      word = word.split('').sort().join('');
    }

    if (uniques.indexOf(word) === -1) {
      uniques.push(word);
    }
  });

  if (words.length === uniques.length) {
    return true;
  }
  return false;
}
Advent of code luke 5 i Haskell
SPOILER ALERT! Vis spoiler

Ikke noe fancy, ser ut som den kanskje misser tail call optimization, men orker ikke finne ut nå

Kode

import Data.Sequence 
data CPU = CPU !Int !Int (Seq Int)

main =  do
        textBlob <- readFile "dec05.txt"
        let tape = fromList (map read (lines textBlob))
        print(process (CPU 0 0 tape))

process (CPU clock ip tape)
    | ip < 0 = clock
    | ip >= Data.Sequence.length tape = clock
    | otherwise = let jump = tape `index` ip
                      nextJmp = if jump >= 3 then jump - 1 else jump + 1
                      mutedTape = update ip nextJmp tape
        in process (CPU (clock + 1) (ip + jump) mutedTape)
NOOOOOOOOOOOOOOOOOO-
robhol's Avatar
AoC-rollup fra forrige gang:

Dag 3: https://gist.github.com/robhol/328c4...284bc2662ac950
Dag 4: https://gist.github.com/robhol/d57bc...be50487559d473
Dag 5: https://gist.github.com/robhol/e1604...eb03ce6b7038d9
Dag 6: https://gist.github.com/robhol/18207...35f59adb23b773 (Ikke den mest elegante løsningen...)

Har også løsning på 7, men ikke lyst til å poste den samme dag.
AoC Dag 6 i Python:

SPOILER ALERT! Vis spoiler

Litt quick'n'dirty-løsning for del 2. Kunne sikker integrert de bedre. I del 1 utfører jeg bare algoritmen de spesifiserer, og lagrer hver tilstand i en dict. Med en gang jeg ser at dicten har en tidligere tilstand så avbryter jeg.

I del 2 så gjør jeg akkurat det samme, men nullstiller dicten når jeg ser første sykel. Setter samtidig et flagg som gjør at neste gang sykelen startes, så avbrytes loopen.

Kode

memos = {}
banks = map(int,open("6.txt").read().split()) #[0,2,7,0]
 
def realloc(b):
    ix_hi = b.index(max(b))
    blocks = b[ix_hi]
    b[ix_hi] = 0
    ix = (ix_hi + 1) % len(b)
    while blocks > 0:
        b[ix] += 1
        blocks -= 1
        ix = (ix + 1) % len(b)
    return b
 
# Part 1
cycles = 0
while True:
    memostring = ','.join(map(str,banks))
    if memostring in memos:
        break
 
    memos[memostring] = True
    cycles += 1
    realloc(banks)
print cycles
 
# Part 2
cycles = 0
seen_cycle = False
while True:
    memostring = ','.join(map(str,banks))
    if memostring in memos:
        if seen_cycle:
            break
        seen_cycle = True
        memos = {}
 
    memos[memostring] = True
    if seen_cycle:
        cycles += 1
    realloc(banks)
print cycles
AoC dag 10 i Golang: (dette er kun part2, men det er små endringer fra part1)

SPOILER ALERT! Vis spoiler

Kode

package main

import "fmt"

const N int = 256

var input []byte = append([]byte("70,66,255,2,48,0,54,48,80,141,244,254,160,108,1,41"), 17, 31, 73, 47, 23)

type Circ []byte

func NewCirc() Circ {
	c := make(Circ, N)
	for i := 0; i < N; i++ {
		c[i] = byte(i)
	}
	return c
}

func (c Circ) Get(i int) byte {
	return c[(i+N)%N]
}

func (c Circ) Put(i int, val byte) {
	c[(i+N)%N] = val
}

func (c Circ) Reverse(start, length int) {
	for i, j := start, start+length-1; i < j; i, j = i+1, j-1 {
		tmp := c.Get(i)
		c.Put(i, c.Get(j))
		c.Put(j, tmp)
	}
}

func ToDense(s []byte) []byte {
	dense := make([]byte, 16)
	for i, _ := range dense {
		x := s[i*16+0]
		for j := 1; j < 16; j++ {
			x ^= s[i*16+j]
		}
		dense[i] = x
	}
	return dense
}

func main() {
	c := NewCirc()
	curr := 0
	i := 0
	for round := 0; round < 64; round++ {
		for _, length := range input {
			c.Reverse(curr, int(length))
			curr += int(length) + i
			i++
		}
	}
	dense := ToDense([]byte(c))
	for _, d := range dense {
		fmt.Printf("%02x", d)
	}
	fmt.Println()
}
Sist endret av Ozma; 10. desember 2017 kl. 17:59.
▼ ... over en uke senere ... ▼
Dagens Knowit-oppgave (Luke 18, islandsk-kryptering) forklarte ikke dette med "5 bits" så nøye, så her er et hint:
SPOILER ALERT! Vis spoiler
Det er 32 bokstaver i alpfabetet som er oppgitt. Den første er 0b0, den andre er 0b1, den siste er 0b11111, and so on.