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.
  6 5924
NOOOOOOOOOOOOOOOOOO-
robhol's Avatar
Andre poster i serien:
Programmeringsnøtt: 10 000 (scoring av terningspill)
Programmeringsnøtt 2: Electric Boogaloo - Norske tallord (oversett tall til godt norsk)

Bakgrunn
Denne oppgaven bygger på det britiske gameshowet Countdown (8 Out of 10 Cats Does Countdown-versjonen med bl.a. Jimmy Carr anbefales og er morsomt selv for det litt tørre premisset) og to av hovedrundene i showet. Episoder kan finnes på Youtube, i hvert fall av sistnevnte, som jeg vil anbefale.



Oppgave 1: Letters round (Enkel)
Konseptet i denne runden er at paneldeltakerne får delt ut totalt 9 tilfeldige bokstaver, og kan velge antall konsonanter og vokaler. De får så 30 sekunder på seg til å sette sammen det lengste mulige ordet ved å bruke bokstavene.

I denne oppgaven skal du ta inn en liste med bokstaver og produsere forskjellige ord som kan bygges opp kun ved hjelp av disse - lengste ord først.

Verdt å merke seg:
  • Én enkelt trukket bokstav kan bare brukes én gang (men bokstaver kan trekkes flere ganger)
  • Du kan bruke en ekte ordliste eller mocke din egen. Showet bruker Oxford Dictionary of English. Engelske ordlister finnes på nett.
For en ekstra utfordring:
  • I showet er det i utgangspunktet ikke lov med egennavn, andre kapitaliserte ord, ord med bindestrek eller amerikansk-engelske ord.
  • Reglene tillater bøyde former av verb og adjektiver (-er, -est), flertallsformer (-s)

Eksempel:
Du får inn bokstavene "IOLTDIEGC". Beste mulige svar er "idiolect" for 8 poeng. Det finnes også mange andre løsninger for 7, 6, ... poeng.



Oppgave 2: Numbers round (Vanskelig)
I denne runden får paneldeltakerne 6 tilfeldige tall. De kan velge 0-4 "store" tall (25, 50, 75, 100) og resten er "små" tall (1-10 som hver kan forekomme to ganger). Et tilfeldig tall fra 100-999 blir trukket, og deltakerne får 30 sekunder på seg til å komme fram til samme tall (eller nærmest mulig) ved å bruke alminnelige regneoperasjoner.

Oppgaven din er å ta inn en liste med 6 tall, samt et måltall, og finne måter å regne seg fram til måltallet gitt kun de 6 tallene. "Nesten riktige" (+/- 10 eller mindre) svar er også interessante.

Verdt å merke seg:
  • Kun addisjon, subtraksjon, multiplikasjon og divisjon.
  • Tallene som er trukket må ikke nødvendigvis brukes.
  • Hvert trukket tall kan maksimalt brukes én gang (de små tallene kan bli trukket opp til 2 ganger hver)
  • Du kan bruke så mange mellomregninger du vil, og trenger ikke angi ett enkelt sammenhengende uttrykk
  • Alle mellomregninger må resultere i et positivt heltall. Du kan ikke trekke fra eller dele hvis du ender opp med et negativt tall eller et desimaltall på noe tidspunkt.
  • Du får poeng for svar som er maksimalt 10 unna målet.

Eksempel:
SPOILER ALERT! Vis spoiler

Deltakeren har valgt 2 store og 4 små tall. Tallene trekkes og er: 25, 75, 10, 7, 5, 4. Måltallet trekkes og er 459.
Løsning 1:
75 - 10 = 65
65 * 7 = 455
455 + 4 = 459. Kan også uttrykkes som: (75 - 10) * 7 + 4.

Løsning 2:
75 / 25 = 3
3 + 10 = 13
13 * 7 = 91
91 * 5 = 455
455 + 4 = 459. Kan også uttrykkes som: (10 + 75 / 25) * 7 * 5 + 4

Løsning 3:
10 + 7 = 17
75 / 25 = 3
4 + 5 = 9
17 * 3 * 9 = 459. Kan også uttrykkes som: (10 + 7) * 75 / 25 * (4 + 5)


For en ekstra utfordring:
  • Prøv å finne den enkleste eller mest intuitive fremgangsmåten (YMMV)
  • Mange svar er trivielt likeverdige fordi addisjon og multiplikasjon er kommutative:
    4 + 7 * (75 - 10)
    4 + (75 - 10) * 7
    7 * (75 - 10) + 4
    (75 - 10) * 7 + 4
    Prøv å luke ut disse.




--

Lykke til. Jeg kommer til å vente litt før jeg poster løsningene mine (hvis jeg husker det). Som alltid, spør hvis noe er uklart.
Sist endret av robhol; 4. juli 2019 kl. 14:13.
Oppgave 1:

Sitat av robhol Vis innlegg
For en ekstra utfordring:
  • I showet er det i utgangspunktet ikke lov med egennavn, andre kapitaliserte ord, ord med bindestrek eller amerikansk-engelske ord.
  • Reglene tillater bøyde former av verb og adjektiver (-er, -est), flertallsformer (-s)
Vis hele sitatet...
Dette avhenger helt av hva slags ordlister en finner, og fant det selv vanskelig å finne noen veldig bra, spesielt noen som følger Oxford Dictionary of English.

Kode

import io
#Wordlist from https://github.com/dwyl/english-words

def read_wordlist(filename):
    with io.open(filename) as f:
        return [line.rstrip('\n').lower() for line in f]

def contains_all(letters, word):
    return all(word.count(c) <= letters.count(c) for c in word)

def main():
    wordlist = read_wordlist('words_alpha.txt')
    letters = input('Letters: ').lower()
    output = [word for word in wordlist if contains_all(letters, word)]
    print (f'Possible words are:')
    for w in reversed(sorted(output, key=len)):
        print(f'{len(w)}: {w}')


if __name__ == '__main__':
    main()
Demo på repl.it


Litt lyst å gjøre et forsøk på å løse denne i brainfuck.

Oppgave 2:
Ingen anelse hvor jeg skal begynne engang, får se om finner tid til å finne på noe lurt her.
Sitat av robhol Vis innlegg
Oppgave 2: Numbers round (Vanskelig)
I denne runden får paneldeltakerne 6 tilfeldige tall. De kan velge 0-4 "store" tall (25, 50, 75, 100) og resten er "små" tall (1-10 som hver kan forekomme to ganger).
Vis hele sitatet...
Betyr dette at deltakeren kanpåvirke hvilke tall de får? At de selv kan velge om de vil 0 eller 4 store tall f.eks? Jeg forstår det er tilfeldig hvilke tall de får, men kan de selv påvirke fordelinga?
Sitat av robhol Vis innlegg
Et tilfeldig tall fra 100-999 blir trukket, og deltakerne får 30 sekunder på seg
Vis hele sitatet...
Så måltallet blir trukket etter at deltakerne har blitt tildelt sine seks tall?

Sitat av robhol Vis innlegg
Alle mellomregninger må resultere i et positivt heltall. Du kan ikke trekke fra eller dele hvis du ender opp med et negativt tall eller et desimaltall på noe tidspunkt.
Vis hele sitatet...
Dette kravet fremstår som litt pussig. Betyr det at jeg ikke får lov til å skrive 1-2+3, men får lov til å skrive 3-2+1? Eller ønsker du at man begynner bakerst, slik at første er lovlig, men den andre ulovlig? I mitt hode ville jeg i begge tilfeller evaluere hele smæla i en go, uten å kuke rundt med mellomregninger.
Rent matematisk, siden du eksplisitt har sagt at subtraksjon er en tillatt operasjon, så skjønner jeg at du godtar f.eks 7-4 = 3. Men rent formelt har jeg jo nå utført en ulovlig mellomregning, har jeg ikke? I alle fall på en datamaskin! 4 var et positivt heltall helt til jeg gjorde det negativt og la resultatet til 7. Mulig jeg fremstår urimelig pedantisk her nå, men for å illustrere poenget mitt: (2-1)*(2+1) - noen vil si at du her førsk skal evaluere parentesenes innhold, og så multiplisere resultatet, men den konvensjonelle regelen man lærer på skolen er gange de ut og så evaluere stykkvis, og det er også lovlig. Jeg spammer med parenteser for unngå misforståelser, så brace yerself: vi får ((2*2) + (2*1) - (1*2) - (1*1)). Dette er opplagt er innafor, fordi alle mellomregningene er positive. Eller, er det? Jeg skal nå summere 4 + 2 - 2 - 1, og da er vi tilbake ved utgangspunktet. Det beror på om jeg begynner bakerst eller forrerst når jeg legger sammen mellomproduktene...
Videre, som du påpeker er multiplikasjon kommutativt. Så hva om jeg i steden skriver (2+1)*(2-1) = ((2*2) + (2*(-1)) + (1*2 ) + (1*(-1))) ? Nå har jeg i alle fall utført to ulovlige mellomregninger! Med andre ord, hvis jeg fôrer evalfunksjonen min med "(2-1)*(2+1)", så må jeg ha detaljkunnskap om om hva som skjer under panseret for å vite om jeg har juksa eller ei? Jeg skal være veldig forsiktig med å uttrykke meg bastant om fundamental matematikk, men jeg er rimelig sikker på at dersom sluttresultatet er et positivt heltall, så eksisterer det en lovlig løsning. Blir ikke da dette kravet litt kunstig?
Sist endret av Myoxocephalus; 8. juli 2019 kl. 11:28.
NOOOOOOOOOOOOOOOOOO-
robhol's Avatar
Trådstarter
Svarene er "ja" på de fire første, og "reglene er ikke mine" på resten. Jeg kan være enig i at regelen om negative tall (og til en viss grad desimaltall) er litt sær, jeg ser heller ikke egentlig poenget. Likevel er det en regel, så jeg tok det med. Resten er ikke relevant.

Jeg kan anbefale å ta en titt på Youtube der jeg mistenker at man kan se segmentet "in action" for å få en bedre følelse av hvordan det foregår enn jeg kan formidle her. Det er også eksempler på utregninger i førstepost.
Sitat av Lanjelin Vis innlegg
SPOILER ALERT! Vis spoiler

Kode

import io
#Wordlist from https://github.com/dwyl/english-words

def read_wordlist(filename):
    with io.open(filename) as f:
        return [line.rstrip('\n').lower() for line in f]

def contains_all(letters, word):
    return all(word.count(c) <= letters.count(c) for c in word)

def main():
    wordlist = read_wordlist('words_alpha.txt')
    letters = input('Letters: ').lower()
    output = [word for word in wordlist if contains_all(letters, word)]
    print (f'Possible words are:')
    for w in reversed(sorted(output, key=len)):
        print(f'{len(w)}: {w}')


if __name__ == '__main__':
    main()
Vis hele sitatet...
Jeg ble veldig nysgjerrig på hvorfor du importerte io og brukte io.open() i stedet for å bare bruke den innebygde open(). Etter litt googling, så ser det for meg ut til at det ikke er noe som helst forskjell i Python 3 (som du jo bruker, siden du bruker f-strings). Eller er det en grunn til at du bruker det som jeg ikke tenker over? Er alltid på utkikk etter tips og triks i Python, så dette ble jeg interessert i!
Kan enkelt bare bruteforce alle kombinasjonene av tall og operasjoner, når det er så få tall som 6. Ble ikke så veldig sexy loop når jeg måtte lagre mellomregninger underveis, men for eksempelet ditt over så vil noe sånt som det her fungere:

Kode

from itertools import product
from collections import defaultdict

def gen_all_combos(part_sum, numbers_left, history=None):
    combos = product("+-*/", numbers_left)
    if not history:
        history = str(part_sum)
    for combo in combos:
        numbers_left_copy = list(numbers_left[:])
        numbers_left_copy.remove(combo[1])
        calc_string = history+''.join(map(str,combo))
        result = eval(calc_string)
        if result < 0 or abs(int(result)-result) > 1e-6:
            continue
        yield int(result), numbers_left_copy, '('+calc_string+')'

NUMBERS = [25, 75, 10, 7, 5, 4]
TARGET = 459
solutions = defaultdict(set)
for num in NUMBERS:
    nums = NUMBERS[:]
    nums.remove(num)
    for c1 in gen_all_combos(num, nums):
        solutions[c1[0]].add(c1[2])
        for c2 in gen_all_combos(*c1):
            solutions[c2[0]].add(c2[2])
            for c3 in gen_all_combos(*c2):
                solutions[c3[0]].add(c3[2])
                for c4 in gen_all_combos(*c3):
                    solutions[c4[0]].add(c4[2])
                    for c5 in gen_all_combos(*c4):
                        solutions[c5[0]].add(c5[2])
                        for c6 in gen_all_combos(*c5):
                            solutions[c6[0]].add(c6[2])
print(solutions[459])
Kjører på noen sekunder her.
Sist endret av Dyret; 9. juli 2019 kl. 02:09.
Sitat av Realist1 Vis innlegg
Jeg ble veldig nysgjerrig på hvorfor du importerte io og brukte io.open() i stedet for å bare bruke den innebygde open(). Etter litt googling, så ser det for meg ut til at det ikke er noe som helst forskjell i Python 3 (som du jo bruker, siden du bruker f-strings). Eller er det en grunn til at du bruker det som jeg ikke tenker over? Er alltid på utkikk etter tips og triks i Python, så dette ble jeg interessert i!
Vis hele sitatet...
Har nokså nylig tatt skrittet og flyttet over til å bruke Python 3, så dette henger igjen fra det å skrive for Python 2.7.