Advent of code

minapamina

Tukijäsen
Liittynyt
17.10.2016
Viestejä
1 201
Pakollinen muistutus tännekkin, osallistukaa Advent of Code 2018 joulukanlenteriin. Joka päivä 2 "haastetta", kivaa puuhaa eikä tarvitse syödä suklaata :)

Toteutuskielen voi valita itse, sillä ainoa mikä merkkaa on tulos. Eli jokseenkin aloittelijaystävällinen, ja sopii kaikille kielestä riippumatta.

E: Linkki vuodelle 2019 Advent of Code 2019
 
Viimeksi muokattu:
Kiitoksia, tämähän on hauska homma. Nämä on siitä mukavia että saa kivasti vähän muistinvirkistystä ja pientä pähkinää purtavaksi sopivaa ratkaisumallia miettiessä.
 
Mitenköhän olen onnistunut missaamaan tämän aiempina vuosina. Vaikuttaa hyvältä näin parin ensimmäisen päivän tehtävien perusteella. :tup: Jos ei tarttis yöllä nukkua niin olisi hauska testata miten pärjäisi tuolla leaderboardilla...
 
Mitenköhän olen onnistunut missaamaan tämän aiempina vuosina. Vaikuttaa hyvältä näin parin ensimmäisen päivän tehtävien perusteella. :tup: Jos ei tarttis yöllä nukkua niin olisi hauska testata miten pärjäisi tuolla leaderboardilla...

Sama homma ittellä, no ompahan kevääksi tekemistä jos viittii käydä vanhempia vuosia läpi.
 
Advent of Code on taas täällä. Mun ekan päivän ratkaisu tässä Javascriptillä tehtynä:

JavaScript:
const { expenseReport } = require("./expense");

const findEntries = (expenseReport) => {
  const sum = 2020;
  const correctNums = [];

  expenseReport.every((num1) => {
    expenseReport.slice(1).every((num2) => {
      if (num1 + num2 === sum) {
        correctNums.push(num1);
        correctNums.push(num2);
        return false;
      }
      return num2;
    });

    if (correctNums.length) {
      return false;
    }
    return num1;
  });

  return correctNums[0] * correctNums[1];
};

findEntries(expenseReport)

Olisi kiva nähdä mitä ratkaisuja muut saa aikaan.

EDIT: Jaa tossa onkin kaksi osaa.
 
Advent of Code on taas täällä. Mun ekan päivän ratkaisu tässä Javascriptillä tehtynä:

JavaScript:
const { expenseReport } = require("./expense");

const findEntries = (expenseReport) => {
  const sum = 2020;
  const correctNums = [];

  expenseReport.every((num1) => {
    expenseReport.slice(1).every((num2) => {
      if (num1 + num2 === sum) {
        correctNums.push(num1);
        correctNums.push(num2);
        return false;
      }
      return num2;
    });

    if (correctNums.length) {
      return false;
    }
    return num1;
  });

  return correctNums[0] * correctNums[1];
};

findEntries(expenseReport)

Olisi kiva nähdä mitä ratkaisuja muut saa aikaan.

EDIT: Jaa tossa onkin kaksi osaa.

Mä nakuttelin jotain tällaista. Vähän purkka tuo funktio (ja varmaan hitaanpuoleinenkin), mutta näyttäisi ajavan asiansa:
JavaScript:
const expenses = [
  1509,
  1857,
  1736,
  1815,
  1576,
  1970,
  1567,
  1778,
  1508,
  1833,
  1377,
  1890,
  1375,
  1396,
  1102,
  1639,
  1818,
  1469,
  1138,
  1333,
  1906,
  1557,
  1686,
  1712,
  1990,
  1930,
  1761,
  1881,
  1551,
  1627,
  1801,
  1728,
  1960,
  1407,
  1832,
  1842,
  1393,
  1870,
  1295,
  1528,
  251,
  1945,
  1589,
  1850,
  1650,
  1793,
  1997,
  1758,
  1477,
  1697,
  1081,
  1825,
  1899,
  1171,
  1104,
  1839,
  1974,
  1630,
  1831,
  1671,
  1723,
  1811,
  1489,
  1647,
  1486,
  1107,
  1786,
  1680,
  1942,
  1640,
  1112,
  1703,
  1315,
  1769,
  1966,
  997,
  2010,
  1635,
  1196,
  383,
  1986,
  1860,
  1743,
  1756,
  1555,
  1111,
  1823,
  48,
  1953,
  1083,
  1804,
  1933,
  1626,
  1895,
  1807,
  1669,
  1783,
  389,
  1821,
  1883,
  1114,
  1587,
  1941,
  1725,
  1646,
  456,
  1550,
  1939,
  1975,
  1324,
  1201,
  1018,
  1001,
  1402,
  1885,
  1481,
  1633,
  1781,
  1622,
  1822,
  1559,
  1696,
  1510,
  1251,
  1732,
  1790,
  1813,
  1695,
  1121,
  704,
  1964,
  1984,
  1763,
  1656,
  1183,
  1771,
  1276,
  1764,
  1810,
  1992,
  1213,
  1840,
  1318,
  1965,
  1943,
  1549,
  1768,
  1506,
  1949,
  1739,
  1852,
  1787,
  1570,
  1988,
  1357,
  1909,
  1837,
  561,
  1994,
  1777,
  1547,
  1925,
  1897,
  1817,
  1677,
  1668,
  1982,
  1667,
  1753,
  1041,
  1826,
  1961,
  1797,
  1765,
  1720,
  1835,
  1688,
  1705,
  1744,
  1977,
  1971,
  1775,
  1782,
  1661,
  1385,
  1162,
  1755,
  1846,
  1674,
  1698,
  1882,
  1766,
  1820,
  1531,
  1577,
  1710,
  1382,
  1246,
  1864,
  1702,
];
const sumToMatch = 2020;
const [firstMatch, secondMatch] = expenses
  .map((ex) => {
    const filtered = expenses.filter(
      (ex2) => ex2 === ex || ex2 === sumToMatch - ex
    );
    return filtered.length > 1 ? filtered : null;
  })
  .filter((match) => !!match)
  .shift();
console.log(firstMatch * secondMatch);
 
Tässä myös kakkospäivään minun ratkaisuni:
JavaScript:
const realData = <PROVIDED_LIST_AS_STRING>.split(/\n/).map((entry) => entry.split(' '))
const allValidEntries = realData.filter((entries) => {
  const [min, max] = entries[0].split('-').map(Number);
  const requiredLetter = (/\w?/).exec(entries[1])[0];
  const pw = entries[2];

  const resultLength = pw.split('').filter((letter) => letter === requiredLetter).length;
  return (min <= resultLength && max >= resultLength);
});

Edit: hups, nyt minäkin tajusin mitä edellä tarkoitettiin "kaksiosaisuudella". näissähän on lisätehtäviä :o
 
Tässä oma vastaus kolmanteen päivään:

JavaScript:
const { trees } = require("./trees");

const countTrees = (forest, routes) => {
  // Array of treeCount per route
  const treeArr = [];
  routes.forEach((route) => {
    const [right, down] = route;
    const requiredWidth = forest.length * right;
    const widthFactor = Math.ceil(requiredWidth / forest[0].length);

    const fullForest = forest.map((row) => {
      let newRow = "";
      for (i = 0; i < widthFactor; i++) {
        newRow += row;
      }
      return newRow;
    });

    // Horizontal index
    let hi = 0;
    let treeCount = 0;
    fullForest.forEach((row, vi) => {
      // Skip first row or take multiple steps down if down > 1
      if (vi === 0 || vi % down) {
        return;
      }

      // Increment steps to the right
      hi += right;

      if (row[hi] === "#") {
        treeCount++;
      }
    });
    treeArr.push(treeCount);
  });

  // Multiply treeCounts together
  return treeArr.reduce((acc, cur) => acc * cur, 1);
};

const forest = trees.split("\n");

const routes = [
  [1, 1],
  [3, 1],
  [5, 1],
  [7, 1],
  [1, 2],
];

console.log(countTrees(forest, routes));
 
Täällä on javascript-osaajien kokoontumisajot :interested:

Itse koodaan Pythonilla tai Javalla, ei tuollaisia kieliä.. Mutta siis, mikä idea on laittaa tänne vastauksia? Jos ei ymmärrä ongelmaa, tai ratkaisee sen erittäin elegantisti, niin sitten - mutta nyt nuo on ns. perusratkaisuja ja oikein.

--

Tein tänään kaikki 3 päivää ja meni 15min/tehtävä (= 30min/päivä), kun sain kehitysympäristön pystyyn. Sitten kävin katselemassa ja jotkut vetää alle 3min molemmat tehtävät. Minulla menee se aika tehtävänannon lukemiseen :(
Tämänkin takia noiden ratkaisujen laittaminen on vähän huonoa, kun jos haluaa tulla myöhään mukaan, niin on pakko tehdä itse, ennenkuin käy kurkkimassa, mitä muut ovat tehneet. Tai no minulla on pakko - ja olen myös utelias luenteeltani, niin pakko oli koodata pari tuntia tätä tänään.
 
Täällä on javascript-osaajien kokoontumisajot :interested:

Itse koodaan Pythonilla tai Javalla, ei tuollaisia kieliä.. Mutta siis, mikä idea on laittaa tänne vastauksia? Jos ei ymmärrä ongelmaa, tai ratkaisee sen erittäin elegantisti, niin sitten - mutta nyt nuo on ns. perusratkaisuja ja oikein.

--

Tein tänään kaikki 3 päivää ja meni 15min/tehtävä (= 30min/päivä), kun sain kehitysympäristön pystyyn. Sitten kävin katselemassa ja jotkut vetää alle 3min molemmat tehtävät. Minulla menee se aika tehtävänannon lukemiseen :(
Tämänkin takia noiden ratkaisujen laittaminen on vähän huonoa, kun jos haluaa tulla myöhään mukaan, niin on pakko tehdä itse, ennenkuin käy kurkkimassa, mitä muut ovat tehneet. Tai no minulla on pakko - ja olen myös utelias luenteeltani, niin pakko oli koodata pari tuntia tätä tänään.
Itse en osaa mitään elegantteja ratkaisuja, niin postaan sitten perusratkaisuja. :rofl: Oppimistarkoituksessa perusratkaisuistakin voi olla joillekin harrastelijoille hyötyä. Kaikilla ei ole vuosien ammattimaista ohjelmointikokemusta. Katsoisin toki mielelläni muitten elegantteja tuherruksia ja ottaisin niistä oppia.

Ratkaisuissa on tarkoituksella spoileritägit. Jos joku ei osaa vastustaa niiden avaamista niin en viitsi siitä ottaa vastuuta. :)

Näitten tekeminen jollain muulla kuin pääkielellä voisi olla ihan fiksua. Itsekin voisin vähän verestellä Python-osaamista.
 
Ratkaisuissa on tarkoituksella spoileritägit. Jos joku ei osaa vastustaa niiden avaamista niin en viitsi siitä ottaa vastuuta. :)

Tämä. Jos osaa ratkoa AoC-tehtäviä 15 minuutissa/tehtävä, osaa myös olla klikkaamatta tätä ketjua tai spoilereita :rofl2:
 
Tämä. Jos osaa ratkoa AoC-tehtäviä 15 minuutissa/tehtävä, osaa myös olla klikkaamatta tätä ketjua tai spoilereita :rofl2:

Kaikilla ei ole tämän tason itsehillintää, tämä ei ole osaamiskysymys, vaan haluan katsoa kanssafoorumilaisten koodia uteliaisuuttani :)

..ja se 15min on todella hidas, kun jotkut tekee ne tehtävät 1/10 ajassa (parissa minuutissa). Jos on ekan tehtävän jälkeen input-tiedoston luku valmiina, niin loput tehtävät on tosiaan tuota luokkaa.. Ja tällä suorituksella ei pääse listoille, pitää olla alle 4min yhteensä molempiin tehtäviin.

Nämä ovat mukavia pikku pähkinöitä, joilla mieli pysyy vireänä, niin taidan tehdä loppuun asti - mutta edelleen: jos olen nähnyt jonkun toisen ratkaisun , niin en lähetä omaani kun se olisi lunttausta.
 
Tästähän sai hauskan keinon opetella nyt uudella Macillä Swift-koodausta! Pari ekaa tehtävää tehty, mutta hienoja näistä ei kyllä tule, mutta toisaalta - ei ne ylimääräiset rivit mulle mitään maksakaan! Ajasta kun puhutaan, niin multa meni ainakin 15 minuuttia löytää edes aaltosulut Mac-näppiksestä... :)
 
Nyt olen yli tunnin tehnyt 4.2:sta.. Ei olekaan niin helppoa enää :(

Tai no, koodini on mielestäni oikein, mutta ne tarkistukset ei toimi nyt..

edit: olin kiireessä näpytellyt väärän luvun, kun koetin tehdä tätä mahd. nopeasti. Menikin yli tunti, kun koetin hosua. Tietenkään en koettanut sitä oikeaa vastausta uudestaan, kun oletin väärin.

Sitten kirjoitin ohjelman, joka vie nuo Exceliin ja kävin tuota 30min läpi. Vahvaa suorittamista ja taas meni suurin aika siihen, että näppäilin ohjelman tuloksen väärin. Jos olisi versionhallinta, niin sieltä löytyisi oikea tulos pari iteraatiota takaperin.. Tai [oikea_tulos -1], kun se vikaa riviä seuraava rivi ei ollut tyhjä, niin logiikkani vähän kompasteli.

1607075298931.png

Lisäksi tältä päivältä ei ole tallessa versiota ensimmäisestä tehtävästä, kun .. hosuin.. Ja ei näitä laiteta versionhallintaan.

edit2: en siis ratkaissut tätä Excelillä, vaan mietin ohjelmani bugeja Excelillä. Tai Google Sheetseillä. Tomato, tomato.

edit3: eniten mietin seuraavia asioita, olenko näissä mokannut:
  • pituudessa on välilyöntejä keskellä tai pilkkuja tai kummallisuuksia (ei ollut, kävin datan läpi)
  • regexpini tuolle hiusvärille on väärin (ei ollut :) )
  • hiusvärissä ei tarvitse olla tuota #-merkkiä (tarvitsee)
  • silmäväreissä on joku extraväri, joka pitää huomioida (valitettavasti lzr ei ole validi arvo kuitenkaan, eli ei)
  • pid:n numero ei tunnistu oikein numeroksi, vaikka käytin longia tai etunollat ei mene oikein (aiheeton huoli)
  • cid:iä käytetään jossain (ei käytetty)
 
Viimeksi muokattu:
No nyt kun sait ratkaistua niin voin laittaa oman suorituksen tähän spoiler-tägeihin. :)

JavaScript:
const { passports } = require("./passports");

const reqKeys = ["eyr", "pid", "hgt", "byr", "ecl", "iyr", "hcl"];

const passportIdValid = (ppObj) => {
  for (const key of reqKeys) {
    if (!ppObj.hasOwnProperty(key)) {
      return false;
    }
  }

  const byr = ppObj.byr.length === 4 && ppObj.byr >= 1920 && ppObj.byr <= 2002;
  const iyr = ppObj.iyr.length === 4 && ppObj.iyr >= 2010 && ppObj.iyr <= 2020;
  const eyr = ppObj.eyr.length === 4 && ppObj.eyr >= 2020 && ppObj.eyr <= 2030;

  let hgt = false;
  if (/^\d{2,3}(cm|in)$/.test(ppObj.hgt)) {
    const value = ppObj.hgt.slice(0, ppObj.hgt.length - 2);
    hgt =
      ppObj.hgt.slice(ppObj.hgt.length - 2) === "cm"
        ? value >= 150 && value <= 193
        : value >= 59 && value <= 76;
  }

  const hcl = /^#[0-9a-f]{6}$/.test(ppObj.hcl);
  const ecl = /(amb|blu|brn|gry|grn|hzl|oth)/.test(ppObj.ecl);
  const pid = /^[0-9]{9}$/.test(ppObj.pid);

  return byr && iyr && eyr && hgt && hcl && ecl && pid;
};

const validPassports = (passports) => {
  const validPasswordsCount = passports
    .split("\n\n")
    .map((passport) => {
      const passportObject = passport
        .split("\n")
        .join(" ")
        .split(" ")
        .reduce((acc, cur) => {
          return { ...acc, [cur.slice(0, 3)]: cur.slice(4) };
        }, {});
      return passportObject;
    })
    .filter((ppObj) => {
      if (Object.keys(ppObj).length < 7 || !passportIdValid(ppObj)) {
        return false;
      }
      return true;
    }).length;

  return validPasswordsCount;
};

console.log(validPassports(passports));

Validaattoreiden kanssa oli vähän säätämistä, mutta toimii. :rolleyes:
 
No nyt kun sait ratkaistua niin voin laittaa oman suorituksen tähän spoiler-tägeihin. :)

JavaScript:
const { passports } = require("./passports");

const reqKeys = ["eyr", "pid", "hgt", "byr", "ecl", "iyr", "hcl"];

const passportIdValid = (ppObj) => {
  for (const key of reqKeys) {
    if (!ppObj.hasOwnProperty(key)) {
      return false;
    }
  }

  const byr = ppObj.byr.length === 4 && ppObj.byr >= 1920 && ppObj.byr <= 2002;
  const iyr = ppObj.iyr.length === 4 && ppObj.iyr >= 2010 && ppObj.iyr <= 2020;
  const eyr = ppObj.eyr.length === 4 && ppObj.eyr >= 2020 && ppObj.eyr <= 2030;

  let hgt = false;
  if (/^\d{2,3}(cm|in)$/.test(ppObj.hgt)) {
    const value = ppObj.hgt.slice(0, ppObj.hgt.length - 2);
    hgt =
      ppObj.hgt.slice(ppObj.hgt.length - 2) === "cm"
        ? value >= 150 && value <= 193
        : value >= 59 && value <= 76;
  }

  const hcl = /^#[0-9a-f]{6}$/.test(ppObj.hcl);
  const ecl = /(amb|blu|brn|gry|grn|hzl|oth)/.test(ppObj.ecl);
  const pid = /^[0-9]{9}$/.test(ppObj.pid);

  return byr && iyr && eyr && hgt && hcl && ecl && pid;
};

const validPassports = (passports) => {
  const validPasswordsCount = passports
    .split("\n\n")
    .map((passport) => {
      const passportObject = passport
        .split("\n")
        .join(" ")
        .split(" ")
        .reduce((acc, cur) => {
          return { ...acc, [cur.slice(0, 3)]: cur.slice(4) };
        }, {});
      return passportObject;
    })
    .filter((ppObj) => {
      if (Object.keys(ppObj).length < 7 || !passportIdValid(ppObj)) {
        return false;
      }
      return true;
    }).length;

  return validPasswordsCount;
};

console.log(validPassports(passports));

Validaattoreiden kanssa oli vähän säätämistä, mutta toimii. :rolleyes:

Meillä on sama regexp tuossa hiusvärissä!
 
Tässä omat tämän päivän tehtävät Pythonilla tehtynä. Ensimmäisen osan sain mahtumaan seitsemään riviin, mutta kakkososassa tuli niin paljon tarkastuksia, että päätin tehdä niille oman luokan. Saa antaa palautetta koodista.

Python:
from passports import PassportChecker

def partOne(lines):
    reqFields = ['byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid']
    result = [li for li in lines if all(sub in li for sub in reqFields)]
    return result

def linesToDict(lines):
    lines = partOne(lines)
    lines = [i.split(' ') for i in lines]
    lines = [dict(i.split(':') for i in x) for x in lines]
  
    return lines

def partTwo(lines):
    linesDict = linesToDict(lines)
    count = 0
    for i in linesDict:
        passportCheck = PassportChecker(i)
        if all(passportCheck.testAll()):
            count += 1
    return count


with open('input.txt','r') as f:
    inputStr = f.read().split('\n\n')

lines = [i.replace('\n',' ') for i in inputStr]

print(f'Part one result: {len(partOne(lines))}')
print(f'Part two result: {partTwo(lines)}')
Python:
import re

class PassportChecker:

    def __init__(self, passport):
        self.passport = passport

    def byr(self):
        byr = int(self.passport['byr'])
        if 1920 <= byr <= 2002:
            return True
        return False

    def iyr(self):
        iyr = int(self.passport['iyr'])
        if 2010 <= iyr <= 2020:
            return True
        return False

    def eyr(self):
        eyr = int(self.passport['eyr'])
        if 2020 <= eyr <= 2030:
            return True
        return False

    def hgt(self):
        hgt = self.passport['hgt']
        if hgt[-2:] == 'in':
            if 59 <= int(hgt[:-2]) <= 76:
                return True
        if hgt[-2:] == 'cm':
            if 150 <= int(hgt[:-2]) <= 193:
                return True
        return False
  
    def hcl(self):
        hcl = self.passport['hcl']
        if re.match('^(#[0-9a-fA-F]{6})$', hcl):
            return True
        return False

    def ecl(self):
        ecl = self.passport['ecl']
        colors = ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth']
        if any([sub in ecl for sub in colors]):
            return True
        return False

    def pid(self):
        pid = self.passport['pid']
        if re.match('^([0-9]{9})$', pid):
            return True
        return False

    def testAll(self):
        tests = [self.byr,self.iyr, self.eyr, self.hgt, self.hcl, self.ecl, self.pid]
        result = [f() for f in tests]
        return result
 
Tässä omat tämän päivän tehtävät Pythonilla tehtynä. Ensimmäisen osan sain mahtumaan seitsemään riviin, mutta kakkososassa tuli niin paljon tarkastuksia, että päätin tehdä niille oman luokan. Saa antaa palautetta koodista.

Python:
from passports import PassportChecker

def partOne(lines):
    reqFields = ['byr', 'iyr', 'eyr', 'hgt', 'hcl', 'ecl', 'pid']
    result = [li for li in lines if all(sub in li for sub in reqFields)]
    return result

def linesToDict(lines):
    lines = partOne(lines)
    lines = [i.split(' ') for i in lines]
    lines = [dict(i.split(':') for i in x) for x in lines]
 
    return lines

def partTwo(lines):
    linesDict = linesToDict(lines)
    count = 0
    for i in linesDict:
        passportCheck = PassportChecker(i)
        if all(passportCheck.testAll()):
            count += 1
    return count


with open('input.txt','r') as f:
    inputStr = f.read().split('\n\n')

lines = [i.replace('\n',' ') for i in inputStr]

print(f'Part one result: {len(partOne(lines))}')
print(f'Part two result: {partTwo(lines)}')
Python:
import re

class PassportChecker:

    def __init__(self, passport):
        self.passport = passport

    def byr(self):
        byr = int(self.passport['byr'])
        if 1920 <= byr <= 2002:
            return True
        return False

    def iyr(self):
        iyr = int(self.passport['iyr'])
        if 2010 <= iyr <= 2020:
            return True
        return False

    def eyr(self):
        eyr = int(self.passport['eyr'])
        if 2020 <= eyr <= 2030:
            return True
        return False

    def hgt(self):
        hgt = self.passport['hgt']
        if hgt[-2:] == 'in':
            if 59 <= int(hgt[:-2]) <= 76:
                return True
        if hgt[-2:] == 'cm':
            if 150 <= int(hgt[:-2]) <= 193:
                return True
        return False
 
    def hcl(self):
        hcl = self.passport['hcl']
        if re.match('^(#[0-9a-fA-F]{6})$', hcl):
            return True
        return False

    def ecl(self):
        ecl = self.passport['ecl']
        colors = ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth']
        if any([sub in ecl for sub in colors]):
            return True
        return False

    def pid(self):
        pid = self.passport['pid']
        if re.match('^([0-9]{9})$', pid):
            return True
        return False

    def testAll(self):
        tests = [self.byr,self.iyr, self.eyr, self.hgt, self.hcl, self.ecl, self.pid]
        result = [f() for f in tests]
        return result
Python-koodi on kyllä mukavan näköistä. Itse kun siirryin siitä Javascriptiin vajaa pari vuotta sitten niin oli kyllä vaikea totutella isoon sulkeiden määrään. Koodi näyttää paljon sotkuisemmalta verrattuna Pythoniin.


JavaScript:
const { boardingPasses, boardingPassExample } = require("./boardingPasses");

const getNewRows = (letter, rowRange) => {
  const [lowerLimit, upperLimit] = rowRange;
  const newRowRange = [];

  if (letter === "F" || letter === "L") {
    const newUpperLimit = upperLimit - Math.ceil((upperLimit - lowerLimit) / 2);
    newRowRange.push(lowerLimit, newUpperLimit);
  }

  if (letter === "B" || letter === "R") {
    const newLowerLimit = lowerLimit + Math.ceil((upperLimit - lowerLimit) / 2);
    newRowRange.push(newLowerLimit, upperLimit);
  }

  return newRowRange;
};

const getSeatIds = (boardingPassInput) => {
  const bps = boardingPassInput.split("\n");

  const decryptedBps = bps.map((bp) => {
    let rowRange = [0, 127];
    let colRange = [0, 7];
    let rowResult = null;
    let colResult = null;

    const bpArr = bp.split("");
    bpArr.slice(0, 7).forEach((l, i) => {
      rowRange = getNewRows(l, rowRange);
      if (i === 6) {
        rowResult = rowRange[0];
      }
    });
    bpArr.slice(7).forEach((l, i) => {
      colRange = getNewRows(l, colRange);
      if (i === 2) {
        colResult = colRange[0];
      }
    });
    const seatId = rowResult * 8 + colResult;
    return seatId;
  });
  return decryptedBps.sort((a, b) => a - b);
};

const getMyBoardingPass = (seatIds) => {
  const firstSeat = seatIds[0];
  const lastSeat = seatIds[seatIds.length - 1];

  let sumArr = [];

  for (let i = firstSeat; i <= lastSeat; i++) {
    sumArr.push(i);
  }

  const totalSum = sumArr.reduce((acc, cur) => acc + cur, 0);
  const seatSum = seatIds.reduce((acc, cur) => acc + cur, 0);
  return totalSum - seatSum;
};

console.log(getMyBoardingPass(getSeatIds(boardingPasses)));
 
Oli jokseenkin helppo 5. päivän tehtävä verrattuna tuohon 4. päivään. Tuli jopa omasta mielestä suhteellisen siisti ratkaisu vaikka en ole kieltä paljoa käyttänyt.
C#:
namespace Advent
{
    class Day05
    {
        private static int SeatId(string id)
        {
            id = id.Replace("B", "1");
            id = id.Replace("F", "0");

            id = id.Replace("R", "1");
            id = id.Replace("L", "0");

            return Convert.ToInt32(id, 2);
        }

        public static void Solve(string[] lines)
        {
            int[] seats = Array.ConvertAll(lines, s => SeatId(s));

            Array.Sort(seats);

            Console.WriteLine("Task 1: " + seats[seats.Length - 1]);

            int previous = 0;
            foreach (int seat in seats)
            {
                if (previous > 0 && previous == seat - 2)
                {
                    Console.WriteLine("Task 2: " + (seat - 1));
                    break;
                }
                previous = seat;
            }
        }
    }
}
 
Oli jokseenkin helppo 5. päivän tehtävä verrattuna tuohon 4. päivään. Tuli jopa omasta mielestä suhteellisen siisti ratkaisu vaikka en ole kieltä paljoa käyttänyt.
C#:
namespace Advent
{
    class Day05
    {
        private static int SeatId(string id)
        {
            id = id.Replace("B", "1");
            id = id.Replace("F", "0");

            id = id.Replace("R", "1");
            id = id.Replace("L", "0");

            return Convert.ToInt32(id, 2);
        }

        public static void Solve(string[] lines)
        {
            int[] seats = Array.ConvertAll(lines, s => SeatId(s));

            Array.Sort(seats);

            Console.WriteLine("Task 1: " + seats[seats.Length - 1]);

            int previous = 0;
            foreach (int seat in seats)
            {
                if (previous > 0 && previous == seat - 2)
                {
                    Console.WriteLine("Task 2: " + (seat - 1));
                    break;
                }
                previous = seat;
            }
        }
    }
}
Mulle 5. päivä oli vaikeempi kuin 4. Tulipahan kerrattua binary search.
 
Mukana ollaan. Ja tällä kertaa on tullut tehtyä kaikki Rustilla. Haastetta piisaa siis, koska moni asia tuossa kielessä on vielä täysin outo. Esimerkiksi tämän päivän tehtävässä tuosta olisi varmasti selvinnyt helposti binäärien käytön kautta, mutta taito ei riittänyt. Ratkaisut onneksi löytyivät muita reittejä :)

Tokihan io-tech olisi voinut tehdä vaikka oman leaderboardin?
 
Jäin jumiin päivän 11. ensimmäiseen osaan. Esimerkin vastaus tulee oikein, mutta isommalla inputilla tehdessä tuloksessa on reilun 30 paikan virhe. Mistä mahtaa löytyä virhe?

JavaScript:
const { seats, seatsExample } = require("./seats");

const solve1 = (seats) => {
  const seatArr = seats.split("\n").map((row) => row.split(""));

  const previousRounds = [];
  let prevOccupiedSeats = "";
  let curOccupiedSeats = "";

  do {
    let prevRoundArr = previousRounds[previousRounds.length - 1];
    let curRoundArr;
    if (!previousRounds.length) {
      prevRoundArr = [...seatArr.map((row) => row.map((c) => c))];
      curRoundArr = [...prevRoundArr.map((row) => row.map((c) => c))];
    } else {
      curRoundArr = JSON.parse(JSON.stringify(prevRoundArr));
    }

    prevOccupiedSeats = curOccupiedSeats;
    for (let i = 0; i < curRoundArr.length; i++) {
      const prevRow = prevRoundArr[i - 1];
      const curRow = prevRoundArr[i];
      const nextRow = prevRoundArr[i + 1];
      for (let j = 0; j < curRoundArr.length; j++) {
        const prevRowLeft = prevRow && prevRow[j - 1];
        const prevRowCur = prevRow && prevRow[j];
        const prevRowRight = prevRow && prevRow[j + 1];
        const curRowLeft = curRow[j - 1];
        const curRowCur = curRow[j];
        const curRowRight = curRow[j + 1];
        const nextRowLeft = nextRow && nextRow[j - 1];
        const nextRowCur = nextRow && nextRow[j];
        const nextRowRight = nextRow && nextRow[j + 1];

        const occupiedSeatsAroundArr = [
          prevRowLeft,
          prevRowCur,
          prevRowRight,
          curRowLeft,
          curRowRight,
          nextRowLeft,
          nextRowCur,
          nextRowRight,
        ].filter((seat) => {
          if (seat === "#") return true;
          else return false;
        });

        const occupiedSeatsAround = occupiedSeatsAroundArr.length;

        if (curRowCur === "L" && occupiedSeatsAround === 0) {
          curRoundArr[i][j] = "#";
        } else if (curRowCur === "#" && occupiedSeatsAround > 3) {
          curRoundArr[i][j] = "L";
        }
      }
    }

    previousRounds.push(curRoundArr);

    curOccupiedSeats = JSON.stringify(curRoundArr);
  } while (prevOccupiedSeats !== curOccupiedSeats);
  console.log(
    previousRounds[previousRounds.length - 1]
      .map((row) => row.join(""))
      .join("")
      .split("")
      .filter((char) => char === "#").length
  );
};

const solve2 = (seats) => {};

solve1(seats);
 
9 päivää tehty Pythonilla. Toistaiseksi tuntunut helpommalta kuin vuosi sitten. Ehkä nämä ovat helpompia tai sitten olen parempi. Toki toivon jälkimmäistä :D Pitäisi vaan rohkeammin kokeilla kielen eri ominaisuuksia tai vakiokirjastoja ongelmanratkaisussa niin tulisi uusia tapoja opittua samalla. No, siinäpä hyvä tavoite tuleville päiville.
 
9 päivää tehty Pythonilla. Toistaiseksi tuntunut helpommalta kuin vuosi sitten. Ehkä nämä ovat helpompia tai sitten olen parempi. Toki toivon jälkimmäistä :D Pitäisi vaan rohkeammin kokeilla kielen eri ominaisuuksia tai vakiokirjastoja ongelmanratkaisussa niin tulisi uusia tapoja opittua samalla. No, siinäpä hyvä tavoite tuleville päiville.
Itse en ole oikeastaan koskaan treenannut algoritmejä. Tuntuu, että jo tämän vuoden ongelmia ratkoessa on tullut huomattavaa kehitystä 1. päivään verrattuna.
 
Pitihän tätäkin kokeilla, 1. päivä 15min yhteensä ja 2. päivä 10min + 15min.
Perus javalla, ei mitään hienoa.
 
Tein kans näitä vähän. Aseina PowerShell 7, Python ja JavaScript. Golangilla vois vielä tehdä yhden version.
 
Ei mitään hienostelua, mutta tässä päivän 3 molemmat osat Pythonilla tehtynä.

En tuota metsää lähtenyt renderöimään horisontaalisesti vaan looppasin indeksillä alkuun.

Python:
import os
from math import prod


data_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data.txt')

with open(data_file) as f:
    data = f.read().strip().split('\n')

TREE_SYMBOL = '#'


def count_trees(data, right, down):
    trees = 0
    index = right
    max_index = len(data[0])-1

    for line in data[down::down]:
        if line[index] == TREE_SYMBOL:
            trees += 1

        if index > max_index - right:
            index = index + right - max_index - 1
        else:
            index += right
    return trees


slopes = [[1, 1], [3, 1], [5, 1], [7, 1], [1, 2]]

trees_array = [count_trees(data, *slope) for slope in slopes]

print('Trees product:', prod(trees_array))
 
Päivä 4 tehtynä Pythonilla. Ei vaikea, mutta hyvä tehtävä silti. Melko työläs kun joutui kirjoittelemaan noita validaattoreita. En lähtenyt mitään code golfia tekemään, vaan siltä pohjalta, että koodia on helppo lukea ja ymmärtää sekä skaalata tarpeen mukaan.

STRICT_CHECK parametri säätää katsotaanko 1 vai 2 osa tehtävästä.

Python:
import os
import re

STRICT_CHECK = True
PRINT_INVALID_PASSPORTS = False


class Passport:
    def __init__(self, byr, iyr, eyr, hgt, hcl, ecl, pid, cid='', strict=True):
        if strict:
            assert self.validate_range(byr, 1920, 2002, 'byr')
            assert self.validate_range(iyr, 2010, 2020, 'iyr')
            assert self.validate_range(eyr, 2020, 2030, 'eyr')
            assert self.validate_height(hgt)
            assert self.validate_hair_color(hcl)
            assert self.validate_eye_color(ecl)
            assert self.validate_passport_id(pid)
        self.byr = int(byr)
        self.iyr = int(iyr)
        self.eyr = int(eyr)
        self.hgt = hgt
        self.hcl = hcl
        self.ecl = ecl
        self.pid = pid
        self.cid = cid

    def __str__(self):
        return f'byr:{self.byr} iyr:{self.iyr} eyr:{self.eyr} hgt:{self.hgt} hcl:{self.hcl} ecl:{self.ecl} pid:{self.pid} cid:{self.cid}'

    def validate_range(self, value, min_value, max_value, field=''):
        '''
        validate byr (Birth Year) & iyr (Issue Year) & eyr (Expiration Year)
        byr: four digits; at least 1920 and at most 2002
        iyr: four digits; at least 2010 and at most 2020
        eyr: four digits; at least 2020 and at most 2030
        hgt: cm between 150, 193, in between 59, 76
        '''
        try:
            is_valid_value = min_value <= int(value) <= max_value
            assert is_valid_value
        except:
            raise ValueError(
                f'Range validation failed: min: {min_value} value: {value} max: {max_value} field: {field}')

        return is_valid_value

    def validate_height(self, value):
        ranges = {
            'cm': (150, 193),
            'in': (59, 76)
        }

        try:
            height = re.search(r'^\d+', value).group(0)
            unit = re.search(r'(in|cm)$', value).group(0)
            return self.validate_range(height, *ranges[unit], 'height')
        except:
            raise ValueError(
                f'Height (hgt:{value}) failed, value {value} not in ranges: {ranges}')

    def validate_hair_color(self, value):
        try:
            re.search(r'^#[a-f0-9]{6}$', value).group(0)
            return True
        except:
            raise ValueError(
                f'Hair color (hcl:{value}) failed, not match "#[0-9a-f]6 digits"')

    def validate_eye_color(self, value):
        try:
            re.search(r'^(amb|blu|brn|gry|grn|hzl|oth)$', value).group(0)
            return True
        except:
            raise ValueError(
                f'Eye color (ecl:{value}) failed, not match amb|blu|brn|gry|grn|hzl|oth')

    def validate_passport_id(self, value):
        try:
            re.search(r'^\d{9}$', value).group(0)
            return True
        except:
            raise ValueError(
                f'Passport ID (pid:{value}) failed, not match 9 digit number')


def get_passport_data(file_name):
    data_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), file_name)

    with open(data_file) as f:
        data = f.read().strip()

    return re.split(r'\n\s*\n', data)


def count_valid_passports(passports):
    valid_passport_count = 0
    for index, passport in enumerate(passports):
        passport_params_array = []
        try:
            passport_params_array = sorted(re.split(r'\s', passport))
            passport = Passport(**dict([param.split(':')
                                        for param in passport_params_array]), strict=STRICT_CHECK)
            valid_passport_count += 1
        except Exception as err:
            if PRINT_INVALID_PASSPORTS:
                print(index, err, '---', passport_params_array)
    return valid_passport_count


def main():

    passports = get_passport_data('data.txt')
    valid_passport_count = count_valid_passports(passports)

    print('Valid Passports:', valid_passport_count, f'/ {len(passports)}\n')


if __name__ == '__main__':
    main()
 
9 päivää tehty Pythonilla. Toistaiseksi tuntunut helpommalta kuin vuosi sitten. Ehkä nämä ovat helpompia tai sitten olen parempi. Toki toivon jälkimmäistä :D Pitäisi vaan rohkeammin kokeilla kielen eri ominaisuuksia tai vakiokirjastoja ongelmanratkaisussa niin tulisi uusia tapoja opittua samalla. No, siinäpä hyvä tavoite tuleville päiville.
Laita vähän Pythonia jakoon :)
 

Uusimmat viestit

Statistiikka

Viestiketjuista
261 822
Viestejä
4 548 358
Jäsenet
74 850
Uusin jäsen
Max-fix

Hinta.fi

Back
Ylös Bottom