' freak.no - Programmeringsjulekalendere 2017
freak.no

freak.no (https://freak.no/forum/index.php)
-   Programmering (https://freak.no/forum/forumdisplay.php?f=49)
-   -   Programmeringsjulekalendere 2017 (https://freak.no/forum/showthread.php?t=300650)

Realist1 1. desember 2017 07:06

Programmeringsjulekalendere 2017
 
Ho-ho!

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


Advent of Code:
Sitat:

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.

Knowit Julekalender
Sitat:

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.

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! :D


PS: Si gjerne i fra i denne tråden dersom du vet om flere programmeringsjulekalendere av dette slaget! :)

etse 1. desember 2017 16:30

React-julekalender laget av en kollega: https://react.christmas/

Yochi 1. desember 2017 22:34

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 1. desember 2017 23:35

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);


Realist1 2. desember 2017 01:10

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)


snippsat 2. desember 2017 12:09

[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))


Realist1 2. desember 2017 12:25

Sitat:

Sitat av snippsat (Innlegg 3411429)
[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))


Pent. Hva med del 2? Lurer på om det finnes noen smarte triks.

snippsat 2. desember 2017 13:42

Sitat:

Sitat av Realist1 (Innlegg 3411431)
Pent. Hva med del 2? Lurer på om det finnes noen smarte triks.

Jeg så ikke del 2 i farta :freak:
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)


Realist1 2. desember 2017 14:03

Akkurat ja. Veldig bra.

Tror ikke jeg skal poste min løsning i dag nei. :D

lor3ntz 2. desember 2017 14:33

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]


robhol 2. desember 2017 15:40

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

Dyret 3. desember 2017 19:01

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

snippsat 4. desember 2017 13:32

[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)


Dyret 4. desember 2017 14:18

[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å.

Zepur 4. desember 2017 20:02

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 :freak:

lor3ntz 4. desember 2017 21:21

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


Yochi 4. desember 2017 22:27

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;
}


lor3ntz 6. desember 2017 00:03

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)


robhol 7. desember 2017 10:53

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. ;)

Dyret 7. desember 2017 12:27

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


Ozma 10. desember 2017 16:59

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()
}


Ozma 18. desember 2017 19:20

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.


Alle tidspunkt er GMT +2. Klokken er nå 15:21.