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.
  7 2183
NOOOOOOOOOOOOOOOOOO-
robhol's Avatar
Freak.no utfordres herved til å prøve å finne ut hva følgende "oneliner" gjør:
http://i.imgur.com/EsR04S5.png
Bildet (som er eneste måte å få ok syntax highlighting på) linker til en Github Gist med koden.

For de som ikke er kjent med Python: "X if cond else Y" <==> "cond ? X : Y" i C-familiespråk.

Dictionary-en "values" er utelatt fordi den ville vært en dead giveaway.

Fasit gis, hvis noen bryr seg, om ca. 24 timer eller når jeg kommer på det.
Har koden noen hensikt, eller er det bare en vilkårlig kalkulasjon?
NOOOOOOOOOOOOOOOOOO-
robhol's Avatar
Trådstarter
Den har en hensikt, og det er heller ikke spesielt obskure verdier vi hanskes med.
Ikke trykk på spoilerne om du vil løse oppgaven selv.

SPOILER ALERT! Vis spoiler

Det er summen av bokstavene i en streng, minus 2*summen av kun de bokstavene hvor neste bokstav-verdi er høyere.

For meg virker det som en slags dårlig hash-funksjon, siden det er så mange kollisjoner.


Er jeg på riktig vei?


Her er funksjonen skrevet i et enklere format: (spoilers)
SPOILER ALERT! Vis spoiler

Kode

# -*- coding: utf-8 -*-

import string

# Values mapper a-z til 0-25
values = {char: ord(char) - ord('a') for char in string.ascii_lowercase}

fun1 = lambda inp: sum( [v - 2 * sv for (sv, v) in [ (pv if pv < v else 0, v) for (pv, v) in [ (values[pc] if pc else 0, values[c]) for (pc, c) in zip([None] + list(inp), inp) ]]] )

def fun2(mystr):

    # Get character values. Use 0 if not in values.
    mystr_values = [values.get(char, 0) for char in mystr]

    # Sum character values
    S = sum(mystr_values)

    # Gå gjennom to og to bokstaver.
    # F.eks. "haha" -> "_h, "ha", "ah" og "ha" i den rekkefølgen.
    for prev_value, value in zip([0] + mystr_values[:-1], mystr_values):
        # Hvis tegnverdiene er stigende, trekk fra 2* den forrige.
        # Første bokstav er alltid stigende.
        if prev_value < value:
            S -= 2* prev_value

    return S

for mystr in ["", "heisann", "bob", "kaare", "johnny", "batman", "a", "zz"]:
    assert fun1(mystr) == fun2(mystr)
NOOOOOOOOOOOOOOOOOO-
robhol's Avatar
Trådstarter
Det er på rett spor, men du tenker i for generelle baner.

ASCII er feil, og det er ingen hash-funksjon.
Ok, nå fant jeg en mye bedre løsning:

SPOILER ALERT! Vis spoiler
Det er f.eks. antall verdier som er truthy i en liste.


Kode
SPOILER ALERT! Vis spoiler

Kode

values = {False: 0, True: 1, None: 0}
def fun3(l):
    return sum((1 if b else 0) for b in l)
NOOOOOOOOOOOOOOOOOO-
robhol's Avatar
Trådstarter
Du var nærmere forrige gang, Ozma.

Et par tips relatert til forsøket:
- Algoritmen er mer komplisert enn antall "truthy" verdier.
- I algoritmen du foreslår er values-dicten litt shoehorned, i "riktig" bruksområde er den fullstendig kritisk.

Jeg prøver å komme på noen tips som ikke er instant giveaways, men det er ikke lett.

- Det er ikke en algoritme som er obfuskert med vilje, bare kortfattet, og forhåpentligvis elegant.
- Algoritmen antar at "inp" er gyldig - ingen feilsjekking.
- Reglene for hva som utgjør gyldig input er relativt strenge.

Versjon i funksjonell JavaScript (ES6), ikke så veldig mye klarere, kanskje, men man slipper unna litt nøsting av list comprehensions.

https://gist.github.com/robhol/dc0c2201a9935576bd21

Legger også ut en god gammeldags imperativ løsning i C#.
https://gist.github.com/robhol/20b7c8f24f8658ae6e61
Sist endret av robhol; 24. oktober 2015 kl. 09:48. Grunn: Automatisk sammenslåing med etterfølgende innlegg.
NOOOOOOOOOOOOOOOOOO-
robhol's Avatar
Trådstarter
Oppdatering

Ventet egentlig på mer feedback, men det begynner å bli ørlite grann over 24-timersgrensa nå.

Svaret er: values/lookup er {M:1000, D:500, C:100, L:50, X:10, V:5, I:1} og algoritmen beregner altså verdien av romertall