Il numero originale


36

Linee guida

Scenario

John ha un numero importante e non vuole che altri lo vedano.

Decise di crittografare il numero, attenendosi alla seguente procedura:

Il suo numero è sempre una sequenza non decrescente (es. "1123")

Ha convertito ogni cifra in parole inglesi. (es. "123" -> "ONETWOTHREE")

E poi, riorganizza le lettere in modo casuale. (es. "ONETWOTHREE" -> "ENOWTOHEETR")

John sentiva che il suo numero era sicuro nel farlo. In effetti, tale crittografia può essere facilmente decifrata :(


Compito

Date le stringhe criptate, il tuo compito è decodificarlo e restituire il numero originale.


Regole

  • Questo è il golf del codice, quindi vince la risposta più breve in byte
  • Puoi presumere che la stringa di input sia sempre valida
  • La stringa di input contiene solo lettere maiuscole
  • I numeri originali sono sempre disposti in ordine crescente
  • È possibile restituire il numero in formato stringa o intero
  • Le lettere saranno mescolate solo tra una parola, non tra l'intera stringa.
  • I numeri saranno solo da 1 a 9 inclusi ( ONEa NINE)

Possibile stringa non cifrata

Ecco un elenco delle stringhe subito dopo che sono state convertite in stringhe dai numeri:

 1 -> ONE 
 2 -> TWO
 3 -> THREE
 4 -> FOUR
 5 -> FIVE
 6 -> SIX
 7 -> SEVEN
 8 -> EIGHT
 9 -> NINE

Esempi

"NEO" -> 1

"ENOWOT" -> 12

"EONOTWHTERE" -> 123

"SNVEEGHEITNEIN" -> 789

"ENOOWTEERHTRUOFEVIFXISNEVESTHGIEENIN" -> 123456789

"NOEWOTTOWHEERT" -> 1223


5
In tutti i casi di test, vengono mescolate solo le lettere all'interno di una parola, non le lettere tra le parole. Sarà sempre così?
xnor

1
@xnor Questo sarà sempre il caso. Ho modificato la domanda.
Amorris,

1
allora devi cambiare questo ".... (es." ONETWOTHREE "->" TTONWOHREEE ")"
J42161217

2
@ TessellatingHeckler: una sequenza non strettamente crescente è quando il numero successivo può essere uguale al precedente. 1-1-1-2-2-3 (non strettamente crescente) rispetto a 1-2-3-4-5 (rigorosamente crescente)
koita_pisw_sou

1
Tecnicamente parlando, questa è una codifica, non una crittografia, poiché non esiste una chiave.
Patrick Roberts,

Risposte:


5

Gelatina ,  38  37 byte

ḟ“RGS”O“OX‘,“¢©“¢¢¤‘yF×4/%74ị⁽Gל?9¤Ḍ

Un collegamento monadico che prende un elenco di caratteri (la stringa) e restituisce un numero intero.

Provalo online!

Utilizza un metodo molto diverso dalla risposta Jelly di Pietu1998 , ma ha lo stesso numero di byte ( ho veramente pensato che potrebbe lo ha fatto finire come meno)!

Non si basa sulla monotonicità del numero originale (quindi un input di HTREEWTONOEfunzionerebbe per esempio).

Come?

Prima nota che le parole stesse (e quindi eventuali loro anagrammi) possono essere tutte modificate in parole di lunghezza 4 rimuovendo eventuali R, G e S e sostituendo qualsiasi O con due caratteri (diciamo "12") e qualsiasi X con tre caratteri ( dì "345").

letters  -> -RGS  -> O:12, X:345
ONE         ONE      12NE
TWO         TWO      TW12
THREE       THEE     THEE
FOUR        FOU      F12U
FIVE        FIVE     FIVE
SIX         IX       I345
SEVEN       EVEN     EVEN
EIGHT       EIHT     EIHT
NINE        NINE     NINE

Possiamo quindi mappare il prodotto degli ordinali di quei caratteri sui numeri da 1 a 9 usando l'aritmetica del modulo, a seconda della nostra scelta (il "12345"), quindi cercare questi in un elenco riordinato delle cifre. Il codice in realtà esegue il cast prima dei caratteri e quindi sostituisce gli ordinali, ma è anche possibile in 37 byte con caratteri, ad esempio "DIAAE" ( provalo ).

ḟ“RGS”O“OX‘,“¢©“¢¢¤‘yF×4/%74ị⁽Gל?9¤Ḍ - link: list of characters
 “RGS”                                - literal ['R','G','S']
ḟ                                     - filter discard
      O                               - convert to ordinals
       “OX‘                           - code-page indices list = [79,88]
            “¢©“¢¢¤‘                  - code-page indices lists = [[1,6],[1,1,3]]
           ,                          - pair -> [[79,88],[[1,6],[1,1,3]]]
                    y                 - translate (replace 79s (Os) with [1,6]
                                                       and 88s (Xs) with [1,1,3])
                     F                - flatten into a single list
                       4/             - 4-wise reduce by:
                      ×               -   multiplication (product of each window of four)
                         %74          - modulo 74
                                   ¤  - nilad followed by link(s) as a nilad:
                             ⁽G×      -   base 250 literal = 18768
                                œ?9   -   permutation of [1,2,3,4,5,6,7,8,9] at that
                                      -   index in a lexicographically sorted list of
                                      -   all such permutations -> [1,5,8,2,4,9,7,6,3]
                            ị         - index into
                                    Ḍ - convert from decimal digits to an integer

La tua risposta è letteralmente l'unica risposta in questa pagina che restituisce un valore corretto per: NINEONENIENOENNNIENOENNEINEONEINEONNENIENOINNEINENINNEINENIENNIENNNNIENNEININENIENNENINEINENINENNIEINNEINNENNIENIN.
Magic Octopus Urn l'

+ Punti infinito.
Magic Octopus Urn l'

Grazie! (che mi ha gettato perché ci sono spazi di larghezza zero nel blocco di codice nel commento, ma (wow) funziona )
Jonathan Allan,

Non è comunque un input valido;).
Magic Octopus Urn

Oh wow, non sapevo che sarebbe arrivata una taglia - grazie! Sì, non faceva parte delle specifiche richieste, ho appena creato un metodo che avrebbe funzionato con input non ordinati.
Jonathan Allan,

10

Python 2, 121 117 115 byte

def g(s,a=0,f=''):
 for c in s:
    a+=34**ord(c)%43;r='P!\x83u\x8eI\x92|Z'.find(chr(a))+1
    if r:f,a=f+`r`,0
 return f

-4 byte: dopo tutto quel golf ho dimenticato di inserire una variabile monouso. Lapsus.
-2 byte: rientro a doppia spaziatura → rientro a scheda singola (grazie a Coty Johnathan Saxman); si noti che questo non viene visualizzato correttamente nella risposta.

Ungolfed (compatibile con Python 3):

nums = [80, 33, 131, 117, 142, 73, 146, 124, 90]

def decode(str):
    acc = 0
    final = ''
    for c in str:
        acc += (34**ord(c))%43
        if acc in nums:
            final += str(1+nums.index(acc))
            acc=0
    return final

Ricerca numeri magici:

#!/usr/bin/env python3
from itertools import count, permutations

def cumul(x):
    s = 0
    for v in x:
        s += v
        yield s

all_words = 'ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE'.split()

for modulo in range(1, 1000):
    for power in range(1, 300):
        combinations = []
        for word in all_words:
            my_combination = []
            for perm in permutations(word):
                my_combination += cumul(power**(ord(x)) % modulo for x in perm)
            combinations.append(my_combination)

        past_combinations = set(())
        past_intermediates = set(())
        collision = False
        for combination in combinations:
            final = combination[-1]
            if final in past_intermediates or any(intermediate in past_combinations for intermediate in combination):
                collision = True
                break
            past_combinations.add(final)
            past_intermediates.update(combination)

        if not collision:
            print("Good params:", power, modulo)
            print("Results:", ", ".join(str(x[-1]) for x in combinations))

Spiegazione:

Ho avuto la sensazione di poter rompere insieme i bit ASCII e riassumerli in qualche modo per determinare quando avevo una parola completa. Inizialmente ho provato a fare casino3**ord(letter) e confrontarmi con i risultati attesi, ma ho portato a numeri molto grandi. Ho pensato che sarebbe opportuno forzare un po 'la forza di alcuni parametri, vale a dire il modulo (per garantire che i numeri siano piccoli) e un moltiplicatore per disperdere i numeri in modo diverso nell'intervallo del modulo.

Ho finito per cambiare la variabile del moltiplicatore in una variabile che influenza la potenza stessa perché (da tentativi ed errori) che in qualche modo è riuscito a darmi una risposta golfistica leggermente più breve.

E sopra vedi i risultati di quella forza bruta e un po 'di golf manuale.

Il motivo della scelta 3**xoriginaria è perché sapevo che potevi rappresentare ogni numero lì. Le cifre più ripetute di qualsiasi numero sono due (thrEE, sEvEn, NiNe, ecc.), Quindi ho deciso di considerare ogni input come un numero base-3. In questo modo potrei (mentalmente) rappresentarli come qualcosa di simile 10100000000010020000(tre; un 1 nello tslot, un 1 nello rslot, un 1 nello hslot e un 2 nello eslot). Ogni numero in questo modo ottiene una rappresentazione univoca che può essere facilmente unita raggruppando iterando la stringa e sommando alcuni numeri, e finisce indipendentemente dall'ordine reale delle lettere. Naturalmente, questa non si è rivelata la soluzione ideale, ma la soluzione attuale è ancora scritta con questa idea in mente.


Che cos'è Py3K? ...
CalculatorFeline

Scuse, a cura (è l'antico nome di Python 3)
Score_Under

1
È economico, ma puoi salvare 2 byte (dato che si tratta di Python 2) aumentando il tuo secondo livello di rientro (due spazi) per una singola scheda. [ tio.run/##NU7NCoJAGDy7T/… Provalo online!]
Coty Johnathan Saxman

Inoltre, si potrebbe essere in grado di salvare 6 byte utilizzando letterale \x83, \x8ee \x92nella stringa.
CalcolatriceFeline

@CalculatorFeline Purtroppo il mio interprete non lo fa così: SyntaxError: Non-ASCII character '\xc2' in file <stdin> on line 3, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details. Funziona se inserisco il codingcommento lassù, ma guadagna 15 byte extra.
Score_Under

6

Python 2 , 131 127 byte

s=input()
for y in'WXGURFSOIZ':vars()[y]=s.count(y)
while Z<9:s+=[O-U-W,W,R-U,U,F-U,X,S-X,G,I-X-G-F+U][Z]*str(Z+1);Z+=1
print s

Provalo online!

Basato su una versione corretta della soluzione JavaScript Draco18s .


Che uso interessante di vars!
xnor

@xnor era ovs come me l'ho imparato per altri golf :)))
mdahmoune,

Molto intelligente. Ho un +1 per adattare la mia risposta (imperfetto come in origine).
Draco18s,

5

PHP , 164 byte

for($c=count_chars($argn);$i<9;)echo str_pad("",[$c[79]-$c[87]-$u=$c[85],$c[87],$c[72]-$g=$c[71],$u,$f=$c[70]-$u,$x=$c[88],$c[86]-$f,$g,$c[73]-$x-$f-$g][+$i],++$i);

Provalo online!

PHP , 179 byte

in base all'approccio precedente controlla prima i numeri pari e poi i numeri dispari in ordine crescente

for($z=[$o=($c=count_chars($argn))[87],$f=$c[85],$x=$c[88],$g=$c[71],$c[79]-$o-$f,$c[72]-$g,$v=$c[70]-$f,$c[86]-$v,$c[73]-$x-$v-$g];$i<9;)echo str_repeat(++$i,$z[_405162738[$i]]);

Provalo online!

PHP , 201 byte

for(;$o=ord(WUXGOHFVN[$i]);$i++)for(;$r[$o]<count_chars($argn)[$o];$t[]=$i>3?2*$i-7:2+2*$i,sort($t))for(++$r[$o],$n=0;$q=ord(([TO,ORF,IS,HEIT,EN,TREE,IVE,SEEN,NIE][+$i])[$n++]);)$r[$q]++;echo join($t);

Provalo online!


fallisce perENOOWTWTOWOT
Tito l'

@Titus è ora risolto. Ho frainteso la domanda
Jörg Hülsermann l'

Sì, gli esempi sono in qualche modo fuorvianti. Caspita che è costato! Lo spezzeresti ?!
Tito,

@Titus Penso di aver raggiunto il limite per trovare un altro modo per avvicinarti
Jörg Hülsermann

1
$i++<9e $iinvece di $i<10e ++$i(-1 byte); _405162738[$i]invece di $i%2?$i/2+4:$i/2-1(-4 byte) ( $i/2+~($i%2*-5)funzionerebbe anche, ma quello è più lungo di un byte.)
Tito

5

Javascript (ES6), 288 150 144 byte

q=s=>[u=(l=t=>s.split(t).length-1)`U`,l`O`-l`W`-u,l`W`,l`R`-w,u,f=l`F`-u,x=l`X`,l`S`-x,g=l`G`,l`I`-x-g-f].map((n,i)=>`${i}`.repeat(i&&n)).join``

const testCases = ['NEO', 'ENOWOT', 'EONOTWHTERE', 'SNVEEGHEITNEIN', 'ENOOWTEERHTRUOFEVIFXISNEVESTHGIEENIN']

testCases.forEach(testCase => console.log(testCase, q(testCase)))

Più lungo degli altri due delle altre voci di JS, ma ho pensato di abbandonare un approccio interessante che potrebbe funzionare per qualcuno in un'altra lingua.

In sostanza possiamo determinare quanto segue:

W -> 2
X -> 6
G -> 8
U -> 4

Qualsiasi occorrenza di queste lettere implica che quella cifra esiste nel numero originale. Da qui possiamo dedurre il resto delle cifre:

R-U -> 3
F-U -> 5
S-X -> 7

Compresi i due casi complicati:

O-(U+W) -> 1
I-(X+G+(F-U)) -> 9

Sia 1e 9zona disco relativamente. Per ONE, si Epresenta più di una volta in alcune parole (SEVEN ha due) come fa N( NINE), quindi siamo bloccati a cercareO quale si verifica in altri due posti, fortunatamente entrambi sono semplici.

Per NINE, nove è difficile, non importa come lo tagli.

Quindi finiamo con questa mappa:

[u=(l=t=>s.split(t).length-1)`U`,  //unused 0; precompute 'U's
 l`O`-l`W`-u,    //1
 l`W`,           //2
 l`R`-w,         //3
 u,              //4
 f=l`F`-u,       //5
 x=l`X`,         //6
 l`S`-x,         //7
 g=l`G`,         //8
 l`I`-x-g-f]     //9

9 è in grado di eseguire il back-reference di siX, eiGht e Five (con 5 back-reference foUr) con le assegnazioni variabili, salvando i byte. Grazie a Neil per questo, utilizza diverse funzionalità di JS con cui non ho molta familiarità (le zecche per lo stripping ('a metà, per esempio) e in realtà si avvicina molto all'idea che avevo scarabocchiato sulla carta prima di provare a codificarla (Avevo lasciato 9 come "ciò che è rimasto", pensandoci come "se vedo un Xposso rimuoverlo e un Se Idalla stringa, quindi ..." in modo che dopo i quattro casi semplici i successivi 3 diventino semplice).

Il motivo per cui questa voce è interessante è perché può gestire qualsiasi stringa mescolata come input. cioè piuttosto che le singole parole che vengono mescolate, possiamo mescolare l'intera stringa, che è quello che pensavo che John stesse facendo originariamente:

q=s=>[u=(l=t=>s.split(t).length-1)`U`,l`O`-l`W`-u,l`W`,l`R`-w,u,f=l`F`-u,x=l`X`,l`S`-x,g=l`G`,l`I`-x-g-f].map((n,i)=>`${i}`.repeat(i&&n)).join``

const testCases = ['XENSENINEVSI']

testCases.forEach(testCase => console.log(testCase, q(testCase)))


1
Fantastico, ma c'è un problema nel contare 9 ... Penso che potrebbe essere ixg-f + u
mdahmoune,

@mdahmoune Spara, hai ragione. L'ho incasinato. : <
Draco18s,

Salvare 4 byte usando s.split(t).length-1, 2 byte usando s.repeat(n>0&&n)(perché n è comunque inferiore a zero? Salva 7 byte). Salva un sacco di byte dichiarando gnell'ambito in smodo da non dover continuare a passarlo tutto il tempo, e ancora meglio puoi renderlo un modello con tag, che salva 55 byte in totale (prima della correzione 9). Salva più byte salvando valori ripetuti nel provvisori, e ho rasato un paio di più fuori uso map: s=>[,(l=t=>s.split(t).length-1)`O`-l`W`-l`U`,w=l`W`,l`R`-w,u=l`U`,l`F`-u,x=l`X`,l`S`-x,g=l`G`,l`I`-x-g].map((n,i)=>`${i}`.repeat(n)).join`` .
Neil,

@Neil Non sono sicuro del motivo per cui N sia mai finito a meno di zero, ma lo ha fatto durante i test per TRE. Continuavo a ricevere un errore e, indagando, ho scoperto che era necessario, ma non ne sono ancora sicuro. La mappa della libreria modello che hai lì è javascript che non so nemmeno leggere. : D
Draco18s,

@Neil Ah, giusto, la ragione per la verifica n> 0: Se c'è è un due, ma non tre. R = 0, W = 1. 0-1 = -1. Avevo difficoltà a capirlo un'ora fa, sapevo che era correlato al 3-check, ma stavo avendo un diavolo di tempo a risolverlo (mancanza di caffè).
Draco18s,

4

Mathematica, 133 byte

(s={};c=Characters;j=c@#;Table[If[FreeQ[j~Count~#&/@c[#[[i]]]&@ToUpperCase@IntegerName@Range@9,0],s~AppendTo~i],{i,9}];FromDigits@s)&


ingresso

"VENESGTHIEENNI"

produzione

789


Potresti salvare un byte extra con c@#[[i]]invece di c[#[[i]]]? Potresti essere in grado di salvare un altro byte utilizzando la sintassi infix ~su Table.
numbermaniac,

4

C #, 218 byte

Versione breve:

string q(string s){var n="ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE".Split(',');for(inti=0,j;;i++)for(j=0;n[i].IndexOf(s[j])>=0;){if(++j==n[i].Length){var r=++i+"";for(;j<s.Length;r+=++i)j+=n[i].Length;return r;}}}

Versione estesa:

string q(string s)
{
    var n = "ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE".Split(',');
    for (int i = 0, j; ; i++)
        for (j = 0; n[i].IndexOf(s[j]) >= 0;)
        {
            if (++j == n[i].Length)
            {
                var r = ++i + "";
                for (; j < s.Length; r += ++i)
                    j += n[i].Length;
                return r;
            }
        }
}

Prova ONLINE!

Essendo la mia prima voce, non sono sicuro delle regole ... Sto solo contando la dimensione della classe utilizzata per decifrare, non il codice che la verifica, giusto?

modificare

E per divertirci - ecco cosa ho iniziato a fare, non leggendo le regole complete: S - Guardalo su IdeOne . Decripta anche quando i caratteri di una cifra possono essere rimescolati in qualsiasi punto della stringa.

Modifica 2

Accorciato secondo i suggerimenti di TheLethalCoder. Grazie!

Modifica 3

E ora Tito si è rasato di qualche altro byte. Grazie!


2
Ciao e benvenuto in PPCG! Devi solo includere il metodo, puoi rimuoverlo public staticda. È possibile convertire in un metodo anonimo come s=>{<do stuff>return"";}. È possibile utilizzare varalcune volte, dichiarando le variabili insieme si salvano i byte, ad es int i=1,j;. La creazione di un array da una stringa e la sua divisione in genere è più breve (anche se in questo caso non ho verificato) "ONE|TWO".Split('|'). È possibile utilizzare <0invece di==-1
TheLethalCoder l'


@TheLethalCoder Ottimi consigli, grazie!
SamWhan,

Non testato affatto ma credo che quanto segue sia l'equivalente del tuo codice per 221 byte:s=>{var n="ONE|TWO|THREE|FOUR|FIVE|SIX|SEVEN|EIGHT|NINE".Split('|');for(int i=0,j;++i<= 9;)for(j=0;n[i-1].IndexOf(s[j])<0;){if(++j==n[i-1].Length){var r=i+"";while(j<s.Length){j+=n[i].Length;r+=++i;}return r;}}return "";}
TheLethalCoder

Una nota a margine è di solito più facile usare TIO per i tuoi TIO!
TheLethalCoder

3

JavaScript (ES6), 142 139 byte

Saved 3 Bytes thanks to Neil.

Doesn't currently take advantage of numbers are always arranged in ascending order

f=s=>s?'ENO|OTW|EEHRT|FORU|EFIV|ISX|EENSV|EGHIT|EINN'.split`|`.findIndex(w=>[...s.slice(0,y=w.length)].sort().join``==w)+1+f(s.slice(y)):''

f=s=>s?'ENO|OTW|EEHRT|FORU|EFIV|ISX|EENSV|EGHIT|EINN'.split`|`.findIndex(w=>[...s.slice(0,y=w.length)].sort().join``==w)+1+f(s.slice(y)):''

const testCases = ['NEO', 'ENOWOT', 'EONOTWHTERE', 'SNVEEGHEITNEIN', 'ENOOWTEERHTRUOFEVIFXISNEVESTHGIEENIN']

testCases.forEach(testCase => console.log(testCase, f(testCase)))


wait what?? "axbxc".split`x`.join``. How is this called? Can't seem to find anything on google.
Qwerty

@Qwerty - They are tagged template literals, an ES6 feature which I'm using to save a few bytes by not needing parens in the case of split and join
Craig Ayre

You answered it. I know tagged template literals, but I haven't realised you can use it on these functions as well. Thank you.
Qwerty

They're a little different, you have template literals (e.g. x=`foo${5+5}bar`), they're tagged when you call a function using them without parens: foo`foo${5+5}bar` which is the same as foo(['foo','bar'], 10)
Craig Ayre

1
f(s.slice(y)) is always a string so you don't need the ''+ before it.
Neil

2

Jelly, 38 bytes

Dị“©ȯ¿w¶&ÇhṆỌƘ#Ȯʋ~¢CNẓ_»Ḳ¤FṢŒu
L3*Ç€iṢ

Try it online!

Explanation

L3*Ç€iṢ    Main link. Argument: s (string)
L            Get length of s.
 3*          Raise 3 to that power. This will always be greater than n.
   ǀ        Get the name of each of the numbers using the helper link.
     iṢ      Find the position of the sorted input.

Dị“©ȯ¿w¶&ÇhṆỌƘ#Ȯʋ~¢CNẓ_»Ḳ¤FṢŒu    Helper link. Argument: n (number)
D                                   Get digits of n.
  “©ȯ¿w¶&ÇhṆỌƘ#Ȯʋ~¢CNẓ_»            The string "one two (...) eight nine AA".
                        Ḳ           Split that string at spaces.
 ị                                  Get name of each digit in the list.
                          F         Flatten to a single string.
                           Ṣ        Sort the characters.
                            Œu      Make uppercase.

There is an issue with your code. Try passing the string "EIGHTNINE" into it :)
Amorris

@Amorris fixed for 0 bytes.
PurkkaKoodari

I think it doesn't work for "VENESGTHIEENNI"
J42161217

I second @Jenny_mathy
Amorris

@Jenny_mathy The program is very inefficient and runs out of time and memory for long inputs (I know, it's really bad). You can replace the 3 with 2.2 to use a smaller upper bound, which allows you to easily calculate 789 without changing the working principle. 2 would be nice, but it would barely fail for certain inputs with lots of sixes.
PurkkaKoodari

2

Javascript (ES6), 221 bytes

s=>(m=btoa`8Ñ>Mc¾LtDáNQ!Q>HþHA7átþ4Ò`.split`+`.map(s=>RegExp(s.replace(/(.)\1*/g,c=>`(?=(.*${c[0]}){${c.length}})`))),t=0,r=0,[...s].map(c=>(t+=c,d=1,n=0,m.map((r,i)=>t.match(r)&&(d--,n=i)),d||(r=r*10+n+1,t=0))),r)

Example code snippet:

f=

s=>(m=btoa`8Ñ>Mc¾LtDáNQ…!Q>H…þHA7átþ4Ò`.split`+`.map(s=>RegExp(s.replace(/(.)\1*/g,c=>`(?=(.*${c[0]}){${c.length}})`))),t=0,r=0,[...s].map(c=>(t+=c,d=1,n=0,m.map((r,i)=>t.match(r)&&(d--,n=i)),d||(r=r*10+n+1,t=0))),r)

console.log(f("NEO"))
console.log(f("ENOWOT"))
console.log(f("EONOTWHTERE"))
console.log(f("SNVEEGHEITNEIN"))
console.log(f("ENOOWTEERHTRUOFEVIFXISNEVESTHGIEENIN"))


2

Retina, 160 bytes

([ONE]{3})*([TWO]{3})*([THRE]{5})*([FOUR]{4})*([FIVE]{4})*([SIX]{3})*([SEVN]{5})*([EIGHT]{5})*([NIE]{4})*
$#1$*1$#2$*2$#3$*3$#4$*4$#5$*5$#6$*6$#7$*7$#8$*8$#9$*9

Try it online! Loosely based on @TessellatingHeckler's PowerShell answer.


2

Retina, 88 bytes

[EFIST]

^(ON|NO)*
$#1$*1
O

W
2
HR|RH
3
UR|RU
4
X
6
GH|HG
8
(NN)*$
$#1$*9
r`NV|VN
7
V
5

Try it online!

Explanation

  • First, drop a bunch of unnecessary characters not needed for distinctness
  • Pick the 1s off the front (this lets us drop the rest of the Os immediately after and clears up some Ns before we get to the 5, 7, 9 mess)
  • 2, 3, 4, 6, and 8 are now trivial
  • 9s are a double NN, so grab those off the end before we deal with 5 and 7
  • Replace 7s from the right (so we don't reduce VNV to 75 instead of 57)
  • 5s are the remaining Vs

If you add %(G` to the header, you can use the original code and it will evaluate each line of the input separately: TIO
PunPun1000

Thanks @PunPun1000. I figured there must be a way to do that but gave up after not finding it quickly.
Kytheron

1

PowerShell, 182 bytes

[regex]::Replace("$args",'(?<1>[ONE]{3z2>[TWO]{3z3>[THRE]{5z4>[FOUR]{4z5>[FIVE]{4z6>[SIX]{3z7>[SVEN]{5z8>[EIGHT]{5z9>[NIE]{4})'.replace('z','})|(?<'),{$args.groups.captures[1].name})

Try it online!

Ungolfed but not working code:

[System.Text.RegularExpressions.Regex]::Replace("$args",

    '(?<1>[ONE]{3})       
    |(?<2>[TWO]{3})
    |(?<3>[THRE]{5})
    |(?<4>[FOUR]{4})
    |(?<5>[FIVE]{4})
    |(?<6>[SIX]{3})
    |(?<7>[SVEN]{5})
    |(?<8>[EIGHT]{5})
    |(?<9>[NIE]{4})'

    ,{$args.groups.captures[1].name}
)

e.g. (?<3>[THRE]{5}) matches the character class THRE, so it can match them out of order, and has to match any of these characters five times next to each other, and the capture group is named '3' to map names with numbers.

Rudimentary compression by swapping the repeating text })|(?< for a z.


1

C++, 296, 288 bytes

Short Version:

#define T string
using namespace std;T N[]={"ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN","EIGHT","NINE"};T Q(T S){T R="";for(int i=0;i<9;i++){do{if(S.find(N[i])!=T::npos){S.erase(S.find(N[i]),N[i].size());R+=to_string(i+1);}}while(next_permutation(N[i].begin(),N[i].end()));}return R;}

Full Version:

#define T string
using namespace std;

T N[]={"ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN","EIGHT","NINE"};

T Q(T S)
{
    T R="";
    for(int i=0;i<9;i++)                             //for all possible                             
                                                     //codewords (ONE,TWO...NINE)   
    {
        do
        {   
            if(S.find(N[i])!=T::npos)                //if found in encrypted word
            {
                S.erase(S.find(N[i]),N[i].size());  //erase it from the word
                R+=to_string(i+1);                  //save integer to the result string
            }
                                                    //check next permuation of codeword  

        } while(next_permutation(N[i].begin(),N[i].end())); 
    }                                                   

    return R;
}

Try ONLINE!

Edit:
1) 200->296 bytes, for including namespace and definition of N in the count, as suggested by orlp 2) 296->288, for using macro, thanks to Zacharý


You need to include the definition of N and using namespace std; into your byte count.
orlp

I should be more specific, not just include it in your byte count but also into your answer. Your answer must be able to run just by calling Q right after it without any other additions.
orlp

I re-edited to include it all. For the definition of N i was not sure myself, but for the namespace, I usually dont include it (treat it as library stuff). Though, in the current code it is crucial for the string to work
koita_pisw_sou

1
Can you define a macro to save a few bytes? repl.it/JY7k
Zacharý

1

Ruby, 138 114 110 bytes

gsub(/#{"3ONE3TWO5THRE4FOUR4FIVE3SIX5SEVN5EIGHT4NIE".gsub(/(.)(\D+)/,'([\2]{\1})|')}/){(1..9).find{|i|$~[i]}}

Byte count includes 1 byte for the -p option.

What?

This:

/#{"3ONE3TWO5THRE4FOUR4FIVE3SIX5SEVN5EIGHT4NIE".gsub(/(.)(\D+)/,'([\2]{\1})|')}/

is a regex literal which, through string interpolation, evaluates to:

/([ONE]{3})|([TWO]{3})|([THRE]{5})|([FOUR]{4})|([FIVE]{4})|([SIX]{3})|([SEVN]{5})|([EIGHT]{5})|([NIE]{4})|/

If we assign that to regex, the rest of the code is somewhat easy to grasp: Each match in the input is substituted with the number of the capturing group, extracted from the magical variable $~ which contains the current match data:

gsub(regex){(1..9).find{|i|$~[i]}}

Try it online!


1

Java 8, 198 256 bytes

s->{String r="",x=r;for(String n:"ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE".split(" ")){for(char c:n.toCharArray())x+="(?=.*"+c+")";x+="["+n+"]{"+n.length()+"}x";}for(int i=0,q;i<9;)for(q=(s+" ").split(x.split("x")[i++]).length-1;q-->0;)r+=i;return r;}

+58 bytes.. due to regex of the previous version not working properly (it was also matching "EEE";"EEN";etc.)

Explanation:

Try it here.

s->{                     // Method with String as parameter and return-type
  String r="",           //  Result-String
         x=r;            //  Regex-String
  for(String n:"ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE".split(" ")){
                         //  Loop (1) from "ONE" through "NINE":
    for(char c:n.toCharArray())
                         //   Inner loop (2) over the characters of this String
      x+="(?=.*"+c+")";  //    Append regex-group `(?=\w*c)` where `c` is the capital character
                         //   End of inner loop (2) (implicit / single-line body)
    x+="["+n+"]{"+n.length()+"}x";
                         //   Append regex part `[s]{n}` where `s` is the String, and `n` is the length
  }                      //  End of loop (1)
  // The regex now looks like this, which we can split on "x":
  // (?=.*O)(?=.*N)(?=.*E)[ONE]{3}x(?=.*T)(?=.*W)(?=.*O)[TWO]{3}x(?=.*T)(?=.*H)(?=.*R)(?=.*E)(?=.*E)[THREE]{5}x(?=.*F)(?=.*O)(?=.*U)(?=.*R)[FOUR]{4}x(?=.*F)(?=.*I)(?=.*V)(?=.*E)[FIVE]{4}x(?=.*S)(?=.*I)(?=.*X)[SIX]{3}x(?=.*S)(?=.*E)(?=.*V)(?=.*E)(?=.*N)[SEVEN]{5}x(?=.*E)(?=.*I)(?=.*G)(?=.*H)(?=.*T)[EIGHT]{5}x(?=.*N)(?=.*I)(?=.*N)(?=.*E)[NINE]{4}x
  for(int i=0,q;i<9;)    //  Loop (3) from 0 through 9 (exclusive)
    for(q=(s+" ").split(x.split("x")[i++]).length-1;
                         //   Split the input on the current regex-part,
                         //   and save the length - 1 in `q`
        q-->0;           //   Inner loop (4) over `q`
      r+=i               //    And append the result-String with the current index (+1)
    );                   //   End of inner loop (4)
                         //  End of loop (3) (implicit / single-line body)
  return r;              //  Return the result-String
}                        // End of method

1
Erf... wrong result for "ENOOWTEERHTRUOFEVIFXISNEVESTHGIEENIN" :(
Olivier Grégoire

Yeah, that's the only thing that prevented me to +1 this! My solution was 240 bytes... before you beat me to it.
Olivier Grégoire

@OlivierGrégoire Feel free to post your 240 byte solution, because I'm unable to find a solution.. The disadvantage about [ONE]{3} is that it also matches EEN at the end of that test case with parts of EIGHT and NINE.. And I doubt there is a regex to match all these: ENO|EON|NEO|NOE|OEN|ONE without also matching EEE;EEN;EEO;... for all numbers that is shorter than 40 bytes.. Maybe I can do something using substring and reverse checking the numbers, but I don't really have the time to figure it out now..
Kevin Cruijssen

@OlivierGrégoire If you still have your 240 byte answer, feel free to post it. Just came across this challenge again, and fixed my answer by making a new regex for +58 bytes..
Kevin Cruijssen

1
Well, looks like I found an even shorter way while redoing this challenge :p
Olivier Grégoire

1

Java (OpenJDK 8), 181 bytes

s->{String x="",r;for(int i=0,l;i<9;)for(r="ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE".split(",")[i++],l=r.length();s.matches("["+r+"]{"+l+"}.*");s=s.substring(l))x+=i;return x;}

Try it online!

I took the liberty to reuse Kevin Cruyssen's TIO template. Hope you don't mind ;)


Ah, nevermind my previous comment.. You build the regex, instead of loop over the regex. Still, I was close with my first answer if only I had used the s.substring. The worst part is, is that I am using s.substring in my current answer, lol.. Ah well, +1 from me. Glad it's almost weekend..
Kevin Cruijssen

1

05AB1E, 36 31 bytes

‘€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š‘#vyœN>UvyX:

Try it online!


View it ran with debug: TIO With Debug

‘€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š‘# | Push ['ONE', 'TWO', 'THREE', 'FOUR', 'FIVE', 'SIX', 'SEVEN', 'EIGHT', 'NINE']
vyœ                   | For each list of permutations of that word...
   N>U                | Push index + 1 into register X.          
      vyX:            | Replace each permutation with X.

I was just suggesting you had the green mark rather than me and I noticed a bug: FURONESEV returns FUR1SEV :(
Jonathan Allan

1

Perl 5, 102 + 1 (-n) = 103 bytes

for$i(map{"[$_]{".length.'}'}ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE){$,++;print$,while(s/^$i//)}

Try it online!


Nice! Couple of tricks that help: map{...} can often be replaced with map...,, length and y///c are usually interchangeable too (not always smaller when not working on $_ though!), instead of the while, ++$,x s/^$i// is shorter, and if you change -n to -p you can append to ` $\ ` instead of calling print! Try it online!
Dom Hastings

Also, I hope you don't mind me posting any advice, if you'd prefer I'll refrain. :)
Dom Hastings

0

Python 3, 238 236 bytes

def f(s):
 e=''
 while len(s):
  for i in range(9):
   for r in[''.join(p)for p in permutations('ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE'.split()[i])]: 
    if s[:len(r)]==r:e+=str(i+1);s=s[len(r):]
 return e
from itertools import*

Try it online!


Brute-force solution, doesn't take advantage non-decreasingness of digits.


Thanks to @Mr. Xcoder for saving 2 bytes!


You have to include def f(s): in your byte count, this is not an anonymouos function
Mr. Xcoder

Also you can replace while len(s)>0 with while len(s)
Mr. Xcoder

@Mr.Xcoder thanks for that clarification
Chase Vogeli

You can move the declaration of e into the function header for -1 byte. Also, exec and list comprehensions might save bytes on indentation.
CalculatorFeline

0

PHP, 141 bytes

for($a=count_chars($argn);$c=ord($s[++$p]?:$s=[OWU,W,HG,U,FU,X,SX,G,N17.$p=0][$i-print str_repeat($i++,$x)]);)$x=$a[$i+48]+=($p?-1:1)*$a[$c];

older version, 151 bytes:

for($a=count_chars($argn,1);$s=[OWU,W,HG,U,FU,X,SX,G,N17][+$i++];print str_repeat($i,$a[$i+48]))for($p=0;$c=ord($s[$p]);)$a[$i+48]+=($p++?-1:1)*$a[$c];

loops through the digits from 1 to 9, counting unique characters in the word and subtracting non-unique characters´ counts, printing the digit on the go.
Although it is printing on the go, the digit counts must be stored for the 9 case to work.

Run as pipe with -nR or try it online.

It would save 4 more bytes to store the digit counts in $a[$i] instead of $a[$i+48] and use ASCII 1 and 7 (in quotes) instead of the digit characters themselves.

breakdown

for(
    $a=count_chars($argn,1);                # count character occurences in input
    $s=[OWU,W,HG,U,FU,X,SX,G,N17][+$i++];   # loop through digit names
    print str_repeat($i,$a[$i+48])              # print digit repeatedly
)
    for($p=0;$c=ord($s[$p]);)                   # loop through name
        $a[$i+48]+=                                 # add to digit count
        ($p++?-1:1)*                                # (add first, subtract other)
        $a[$c];                                     # character occurences

ONE is not the only word with an O, so it needs to subtract the counts for W (only appearing in TWO) and U (only appearing in FOUR) and so on.
NINE is special, because there is no way to just subtract if I used the letters (that would require I-X-G-F+U or N-O-S+W+U+X), so I use the digit counts instead.

PHP, 160 bytes

$a=count_chars($argn);foreach([W2O,U4FOR,X6SI,G8I,F5I,O1,R3,S7,I9]as$s)for(${$s[$p=1]}+=$n=$a[ord($s)];$c=ord($s[++$p]);)$a[$c]-=$n;while($$i--?print$i:$i++<9);

assumes all upper case input; characters may be scrambled all over.
Run as pipe with -nR or try it online.

explanation

loops through the digit words, counting their unique characters´ occurences in the input and in the process reducing the count of other characters. "Other characters" could mean all other characters in the word; but only considering those that will be needed later saved 19 bytes.

Transforming the str_repeat loop to a combined loop saved 5 bytes.

And using variable variables for the digit count saved another 8.

breakdown

$a=count_chars($argn);                              # count character occurences in input
foreach([W2O,U4FOR,X6SI,G8I,F5I,O1,R3,S7,I9]as$s)   # loop through digit names
    for(${$s[$p=1]}+=                                   # 2. add to digits count
        $n=$a[ord($s)];                                 # 1. get count of unique character
        $c=ord($s[++$p]);)                              # 3. loop through other characters
        $a[$c]-=$n;                                         # reduce character count
while(
    $$i--?print$i                                       # print digit repeatedly
    :$i++<9);                                       # loop through digits
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.