O número original (II)

18

Esse desafio é essencialmente idêntico a este, com apenas uma diferença: agora é permitido embaralhar letras em qualquer lugar da string.

Cenário

John tem um número importante e não quer que outros o vejam.

Ele decidiu criptografar o número, usando as seguintes etapas:

Seu número é sempre uma sequência não decrescente (ie. "1123")

Ele converteu cada dígito em palavras em inglês. (ie. "123" -> "ONETWOTHREE")

E então, reorganize as letras aleatoriamente. (ie. "ONETWOTHREE" -> "EEWOOHRNTET")

John sentiu que seu número estava seguro ao fazê-lo. De fato, essa criptografia pode ser facilmente descriptografada :(


Tarefa

Dadas as seqüências criptografadas s, sua tarefa é descriptografá-la e retornar o número original.


Regras

  • Este é o código golf, então a resposta mais curta em bytes vence
  • Você pode assumir que a sequência de entrada é sempre válida
  • A sequência de entrada contém apenas letras maiúsculas
  • Os números originais são sempre organizados em ordem crescente
  • Você pode retornar o número no formato string ou número inteiro
  • As letras serão embaralhadas apenas entre uma palavra, não entre toda a cadeia. As letras podem ser embaralhadas em qualquer lugar da string.
  • Os números serão apenas de 1 a 9, inclusive ( ONEa NINE)

Possível seqüência sem codificação

Aqui está uma lista das cadeias de caracteres logo após serem convertidas em cadeias de caracteres a partir dos números:

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

Exemplos

"NEO" -> 1

"NWEOOT" -> 12

"TOEERWNEHOT" -> 123

"IHNEVGENNEISTE" -> 789

"WEETVTRFSVUHNEEFRHIXEOINSNIEGTOONIEE" -> 123456789

"EWHEWROETOTTON" -> 1223

"ONEWESTV" -> 27 (obrigado, ETHproductions!)

Cristian Lupascu
fonte
7
Sugeriu caso de teste: algo como "ONEWESTV" -> 27(inclui um número que na verdade não aparecem)
ETHproductions
@ETHproductions Ótima idéia! Adicionado.
Cristian Lupascu 28/08
Por que não existe o "ZERO"?
RosLuP
@RosLuP John odeia zeros à esquerda ...
Cristian Lupascu

Respostas:

9

Python 2 , 123 bytes

c=map(input().count,"OWHUFXSGIQ")
i=4
for j in"71735539994":c[i*2]-=c[int(j)];i=-~i%5
s=""
for n in c:i+=1;s+=`i`*n
print s

Um programa completo, com entrada citada e impressão do número de João

Experimente online! ou veja uma suíte de testes

Quão?

Vamos trabalhar com o exemplo "NEONSEXTOWNII" (para renderizar 1269, e ser um pouco da Leisure Suite Larry - esque!)

Primeiro c=map(input().count,"OWHUFXSGIQ")recebe a entrada e conta o número de cada um deles OWHUFXSGIQ- estas são as letras que aparecem em cada número em ordem crescente, com 2,4,6 e 8 tendo suas "próprias" letras ( WUXG), mais uma letra extra, Qpara acrescentar um zero até o final e uniformize o comprimento da lista resultante. Para o exemplo:

[2,1,0,0,0,1,1,0,2,0] <- c
 O W H U F X S G I Q  <- is the counts of these letters
 1 2 3 4 5 6 7 8 9 0  <- which "relate to" these digits in John's number
   2   4   6   8   0  <- these will be correct as the letters are unique to their words

As entradas de 1, 3, 5, 7 e 9 precisam ser ajustadas para corrigir a abundância das outras letras. Isso é realizado pelo próximo loop:

i=4
for j in"71735539994":c[i*2]-=c[int(j)];i=-~i%5

Observe que as entradas a serem ajustadas são alternativas (1,3,5,7,9,1,3,5, ...), portanto, podemos adicionar dois a uma variável de índice em cada etapa e módulo por 10 para permanecer em alcance se precisarmos percorrer mais de uma vez (o que fazemos). Para economizar alguns bytes, podemos incrementar em um e módulo em 5 e usar o dobro do índice.
Como os ajustes para 9 exigem o máximo de trabalho que começamos por lá - ele reside no índice 8 e, portanto, começamos em i=4. A string "71735539994"então fornece os índices,, jdos valores a serem removidos em cada estágio (onde garantimos que o nono índice conterá zero usando "Q"ao criar c); c[i*2]-=c[int(j)]executa cada ajuste individual e i=-~i%5passa ipara o próximo índice (onde -~iestá -(-1-i)ou i+1salvando parênteses (i+1)%5) mantendoi*2dentro dos limites de c.
Assim, primeiro subtraímos o número no índice j=7daquele no índice i*2=8, subtraindo o número de "G" contado do número de "I" s, ajustando a contagem de "Nove" pelo número (correto) de "OITO" s ( que também tem um "eu"). Em seguida, passamos para i=0( -~4%5 = (4+1)%5 = 0), referenciando o índice i*2 = 0que é "ONE" e subtraímos o valor encontrado no índice, j=1a entrada contando "W" e, portanto, "TWO", ajustando a contagem de "O" para baixo. No final do loop, temos as contagens corrigidas:

[1,1,0,0,0,1,0,0,1,0] <- c   (for 1223333448 it would be: [1,2,4,2,0,0,0,1,0,0])
 1 2 3 4 5 6 7 8 9 0

então tudo o que resta é imprimir o que cagora representa ( 1269). iagora está de volta 0, então o incrementamos no início do loop e o usamos como nosso dígito:

s=""
for n in c:i+=1;s+=`i`*n
print s

Os back tiques `i`,, são atalhos do Python2 para os repr(i)quais obtém uma representação de string de um objeto (o caractere de dígito em questão como uma string) e multiplicar uma string por um número cria uma nova string com muitas repetições (aqui apenas mostramos n=0o que `i`dizemos "5"to ""e n=1turning keep say "6"as "6", mas também funciona para números inteiros positivos maiores, "3"*4tornando - se, "3333"por exemplo.)

Jonathan Allan
fonte
8

05AB1E , 31 bytes

[{‘Z€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š‘#NSèJ{Q#

Experimente online!

Explicação

[                                   # start loop
 {                                  # sort input
  ‘Z€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š‘#            # push the list ['Z','ONE','TWO','THREE','FOUR','FIVE','SIX','SEVEN','EIGHT','NINE']
                        N           # push the current iteration counter
                         S          # split to list of digits
                          è         # index into the list with each
                           J{       # join to string and sort
                             Q#     # if the strings are equal, exit loop
                                    # implicitly print iteration counter

Muito ineficiente para grandes entradas.

Emigna
fonte
‘Z€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š‘# # push the list ['Z','ONE','TWO','THREE','FOUR','FIVE','SIX','SEVEN','EIGHT','NINE']: você pode explicar um pouco, eu luto para entender como qualquer string pode ser gerada.
Cyril Gandon
1
@CyrilGandon: delimita uma sequência de caracteres separados por maiúsculas e minúsculas. Zmeios Z. Todos os outros pares de dois símbolos indicam uma palavra compactada do dicionário 05AB1E . Então, por exemplo, €µtraduz como ONE.
Emigna
Bom, como você comprime uma string contida no dicionário? Algo com o valor unicode do par?
Cyril Gandon
1
@CyrilGandon: Você pega o número da linha da palavra no ditado (2420 para hello ) e subtrai 1. Isso nos dá 2419. Os símbolos de que precisamos são os símbolos que são seguidos por 24e 19nos documentos . No nosso caso, isso é 24=Ÿe 19=™, então, HELLOseria‘Ÿ™‘
Emigna 31/08
1
Há também um compressor escrito por Adnan que você pode usar na maioria dos casos. O link é um pouco longo, mas você pode encontrá-lo na sala de bate-papo 05AB1E . Isso também é um bom lugar para perguntar se tiver dúvidas :)
Emigna
8

Retina , 112 97 bytes

O`.
}`GH
8
X
6
H
3
+`F(.*)O(.*)U
4$1$2
+`O(.*)W
2$1
+`F(.*)V
5$1
+`N(.*)V
7$1
}`NO
1
NN
9
T`L
O`.

Experimente online!

-12 bytes graças a @Neil

-3 bytes pelo uso de classes de caracteres L na transposição

Como funciona

Basicamente, isso se baseia no fato de que as letras são usadas apenas em determinados nomes de números. Por exemplo, SIXé o único nome que contém um X. Isso fica mais complicado com o fato de algumas palavras se sobreporem às letras, como ambas FIVEe SEVENusando V. Isso pode ser corrigido identificando-se FIVEcom F(.*)V.

fireflame241
fonte
1
@RickHitchcock Fixed. A recursão na conversão para 8 não estava funcionando corretamente
fireflame241
1
@RickHitchcock. Corrigida a recursão para todos eles.
fireflame241
Irritantemente GHe NOseria adjacente, exceto para qualquer anterior 8ou 1de uma substituição antes ...
Neil
Talvez }`GH 8funcionasse 8- isso }faria com que os caracteres fossem classificados novamente, colocando assim qualquer restante Ge Hjuntos.
28417 Neil
@ Neil Boa ideia. Eu também pude fazer isso NO -> 1, o que era conveniente.
precisa saber é o seguinte
5

Kotlin 1.1 , 359 352 331 327 325 bytes

Submissão

fun r(r:String):String{var s=""
val f=r.split(s).groupingBy{it}.eachCount()
val c=Array(10,{0})
c[8]=f["G"]?:0
c[6]=f["X"]?:0
c[4]=f["U"]?:0
c[2]=f["W"]?:0
c[1]=(f["O"]?:0)-c[2]-c[4]
c[3]=(f["R"]?:0)-c[4]
c[7]=(f["S"]?:0)-c[6]
c[5]=(f["V"]?:0)-c[7]
c[9]=((f["N"]?:0)-c[1]-c[7])/2
for(i in 1..9)for(x in 1..c[i])s+=i
return s}

Não funciona no TryItOnline porque o Kotlin 1.1 não é suportado

Teste

fun r(r:String):String{
val f=r.split("").groupingBy{it}.eachCount()
val c=Array(10,{0})
c[8]=f["G"]?:0
c[6]=f["X"]?:0
c[4]=f["U"]?:0
c[2]=f["W"]?:0
c[1]=(f["O"]?:0)-c[2]-c[4]
c[3]=(f["R"]?:0)-c[4]
c[7]=(f["S"]?:0)-c[6]
c[5]=(f["V"]?:0)-c[7]
c[9]=((f["N"]?:0)-c[1]-c[7])/2
var s=""
for(i in 1..9)for(x in 1..c[i])s+=i
return s}

data class TestData(val input: String, val output: String)

fun main(vararg args:String) {
    val items = listOf(
    TestData("NEO" , "1"),
    TestData("NWEOOT" , "12"),
    TestData("TOEERWNEHOT" , "123"),
    TestData("IHNEVGENNEISTE" , "789"),
    TestData("WEETVTRFSVUHNEEFRHIXEOINSNIEGTOONIEE" , "123456789"),
    TestData("EWHEWROETOTTON" , "1223")
    )
    for (item in items) {
        val out = r(item.input)
        if (out != item.output) {
            throw AssertionError("Bad result: $item : $out")
        }
    }
}

Lógica

Lençol de berço

Usei a folha acima para descobrir a maneira mais simples de resolver cada letra

  • Verde = resolver sozinho
  • Azul = Precisa de verduras para resolver
  • Laranja = Precisa de blues para resolver
  • Vermelho = precisa de laranjas para resolver

Editar% s

  • -7 - Alterações no espaço em branco por w0lf
  • -21 - Lista encolhida
  • -4 - Removidos suportes desnecessários
  • 0 - Adicionado lógica em
  • -2 - Reutilizando a string vazia graças a kevin-cruijssen
jrtapsell
fonte
1
Só notei que estou exatamente empatado com você com a minha resposta Java 8 (127 bytes), usando uma abordagem semelhante. ;) Mas uma pergunta: você não pode mudar var s=""e return spara r=""e return rreutilizando a entrada de cadeias, o que você não precisa mais nesse ponto? Eu nunca tinha programado em Kotlin antes, então pode ser que eu fale besteiras aqui. ; p
Kevin Cruijssen
1
Infelizmente não> discuss.kotlinlang.org/t/…
jrtapsell
1
Ah, sim, isso era obviamente uma possibilidade; parâmetros sendo finalpor padrão. Hmm, outra coisa que você pode jogar golfe: coloque var s=""como a primeira coisa no método e substitua val f=r.split("").por val f=r.split(s).. Novamente, não faço ideia se funciona. Pena TIO não suporta v1.1 ainda, caso contrário eu iria tentar estas sugestões mim mesmo antes de eu fazer-me parecer estúpido ..
Kevin Cruijssen
4

Geléia , 37 bytes

1ðDị“©ȯ¿w¶&ÇhṆỌƘ#Ȯʋ~¢CNẓ_»ŒuḲ¤ẎŒ!ċð1#

Experimente online!

-1 graças a Jonathan Allan .

Erik, o Outgolfer
fonte
Este vezes fora para algumas entradas maiores do que 7 caracteres (ex: NINEFIVE, THREEFIVE). É um bug ou o código é apenas ineficiente?
Cristian Lupascu
@ w0lf o último ( Œ!significa "permutações")
Erik the Outgolfer
Salve um byte usando "AA" em vez de "!":...“©ȯ¿w¶&ÇhṆỌƘ#Ȯʋ~¢CNẓ_»...
Jonathan Allan
@JonathanAllan oh é AA uma palavra?
Erik the Outgolfer
É a primeira palavra no dicionário curto, sim.
Jonathan Allan
3

Java 8, 248 234 bytes

s->{int x=0,a[]=new int[10];for(String t:"2WO;4UORF;6XSI;8GI;5FI;7S;3R;1O;9I".split(";"))for(;s.indexOf(t.charAt(1))>=0;a[t.charAt(0)-48]++)for(String z:t.split(""))s=s.replaceFirst(z,"");for(s="";x++<9;)for(;a[x]-->0;)s+=x;return s;}

Código Explicação:

s->{
    // Array to count how often which number appears
    int a[]=new int[10];
    // The first character behind the number serves the identification
    // the other characters get removed to identify the other numbers later
    for(String t:"2WO;4UORF;6XSI;8GI;5FI;7S;3R;1O;9I".split(";"))
        // Check if the string contains the id 
        for(;s.indexOf(t.charAt(1))>=0;a[t.charAt(0)-48]++)
            // Remove the relevant charcters
            for(String z:t.split(""))
                s=s.replaceFirst(z,"");
    // Clear the string to write the output
    s="";
    // write the numbers sequential into the output 
    for(int x=0;x++<9;)
        for(;a[x]-->0;)
            s+=x;
    return s;
}

-14 Agradecimentos a Olivier Grégoire

Edwardth
fonte
1
234 bytes
Olivier Grégoire
2

Java 8, 346 345 344 336 327 bytes

s->{int g=c(s+=" ","G"),u=c(s,"U"),w=c(s,"W"),x=c(s,"X"),f=c(s,"F")-u,h=c(s,"H")-g,v=c(s,"V")-f,o=c(s,"O")-u-w,i=c(s,"I")-f-x-g;return d(s=d(s=d(s=d(s=d(s=d(s=d(s=d(s=d("",o,1),w,2),h,3),u,4),f,5),x,6),v,7),g,8),n,9);}int c(String...s){return~-s[0].split(s[1]).length;}String d(String s,int i,int n){for(;i-->0;s+=n);return s;}

Experimente aqui.

Explicação geral:

Analisei as ocorrências de cada caractere no alfabeto:

E 13357789
F 45
G 8
H 38
I 5689
N 1799
O 124
R 34
S 67
T 238
U 4
V 57
W 2
X 6
  • I primeiro contado todas as ocorrências dos caracteres-Partidas individuais: G=8; U=4; W=2; X=6.
  • Em seguida, todas as ocorrências de caracteres de dois combinados, que também corresponder a um dos quatro acima, o que eu posso subtrair sua contagem: F=5; H=3.
  • Então eu fiz o mesmo novamente para V=7(subtraindo F=5).
  • Em seguida, o mesmo para todos os três jogos personagens que foram deixados: O=1; N=9.
    • Mas como Nhá duas ocorrências NINE, eu tive que fazer um adicional -1para cada ocorrência de N, então usei I=9(subtraindo três correspondências anteriores em vez de duas).

Código Explicação:

s->{                    // Method with String as parameter and return-type
  int g=c(s+=" ","G"),  //  Amount of 8s (and append a space to `s` first, for the .split)
      u=c(s,"U"),       //  Amount of 4s
      w=c(s,"W"),       //  Amount of 2s
      x=c(s,"X"),       //  Amount of 6s
      f=c(s,"F")-u,     //  Amount of 5s
      h=c(s,"H")-g,     //  Amount of 3s
      v=c(s,"V")-f,     //  Amount of 7s
      o=c(s,"O")-u-w,   //  Amount of 1s
      i=c(s,"I")-f-x-g; //  Amount of 9s
  return d(             //  Return the result by:
   s=d(
    s=d(
     s=d(
      s=d(
       s=d(
        s=d(
         s=d(
          s=d("",       //   Making the input String `s` empty, since we no longer need it
                 o,1),  //   Append all 1s to `s`
         w,2),          //   Append all 2s to `s`
        h,3),           //   Append all 3s to `s`
       u,4),            //   Append all 4s to `s`
      f,5),             //   Append all 5s to `s`
     x,6),              //   Append all 6s to `s`
    v,7),               //   Append all 7s to `s`
   g,8),                //   Append all 8s to `s`
  i,9);                 //   And then returning `s` + all 9s
}                       // End of method

int c(String...s){  // Separate method with String-varargs parameter and int return-type
                    //  `s[0]` is the input-String
                    //  `s[1]` is the character to check
  return~-s[0].split(s[1]).length;
                    //  Return the amount of times the character occurs in the String
}                   // End of separated method (1)

String d(String s,int i,int n){
               // Separate method with String and two int parameters and String return-type
  for(;i-->0;  //  Loop from the first integer-input down to 0
      s+=n     //   And append the input-String with the second input-integer
  );           //  End of loop
  return s;    //  Return the resulting String
}              // End of separated method (2)
Kevin Cruijssen
fonte
1
Porra, eu teria pensado que adicionar a uma lista e classificá-la seria mais curto (não é). Bem feito!
Olivier Grégoire
1
Bem, no final, eu outgolfed você , mas não por muito;)
Olivier Grégoire
2

Perl 5 , 100 bytes

Código de 99 bytes + 1 byte para o -nswitch.

${$_}++for/./g;@a=($O-$W-$U,$W,$H-$G,$U,$F-$U,$X,$S-$X,$G,$I-$F+$U-$X-$G);print$_ x$a[$_-1]for 1..9

Experimente online!

Nwellnhof
fonte
1

Python 3 , 225 bytes

def f(s):
	r=[]
	for i,w in zip([2,4,6,8,3,5,7,1,9],["WTO","UFOR","XSI","GEIHT","HTREE","FIVE","VSEEN","ONE","NINE"]):
		while s.count(w[0]):
			r+=[i]
			for l in w:s="".join(s.split(l,1))
	return "".join(sorted(map(str,r)))

Experimente online!

Direto: remova primeiro os dígitos identificados por uma letra específica.

jferard
fonte
1

Python 3 , 125 bytes

lambda s:''.join(min(w)*(2*sum(map(s.count,w[:2]))-sum(map(s.count,w)))for w in"O1WU W2 H3G U4 F5U X6 S7X G8 IUFXG9".split())

Experimente online!

Depois de ler o desafio vinculado, percebi que essa é uma variação da solução Python da mdahmoune , que é baseada na solução ES6 do Draco18s , mas ei, pelo menos, conseguimos dois bytes.

Como essa solução, calculamos a resposta por meio de uma combinação linear do número de ocorrências de certas letras. Codificamos brevemente as combinações lineares, escrevendo-as como palavras nas quais as duas primeiras letras devem ser adicionadas e tudo depois deve ser subtraído. Às vezes, um personagem é necessário para preencher os dois primeiros caracteres; usamos isso para ocultar o dígito que queremos gerar (que nunca ocorrerá na entrada, portanto não afetará nosso algoritmo), com o qual extraímos min.

betaveros
fonte
1

R, 154

u=utf8ToInt(s)-71
m=sum
b=m(u==16)
d=m(u==14)
f=m(u==17)
a=m(u==8)-b-d
g=m(u==12)-f
cat(rep(1:9,c(a,b,m(u==11)-d,d,m(u==15)-g,f,g,m(!u),(m(u==7)-a-g)/2)))

Experimente online!

Sven Hohenstein
fonte
1

Axioma, 351 bytes

s:="GXUWRFVIONETHS";e:EqTable(CHAR,INT):=table();v:=[8,6,4,2,3,5,7,9,1];z:=[k for k in 1..46|prime?(k)];F(x,y)==>for i in 1..#x repeat y;F(z,e.(s.i):=z.i);t:=[1787026,2451,16445,5957,16036207,130169,20372239,495349,20677];h(a)==(r:=1;F(a,r:=r*e.(a.i));j:=[];F(v,while r rem z.i=0 repeat(r:=r quo t.i;j:=cons(v.i,j)));j:=sort j;k:=0;F(j,k:=k*10+j.i);k)

resultados comentados ungolfed

s:="GXUWRFVIONETHS" -- tutte le lettere di ONE..NINE in ordine di importanza 
e:EqTable(Character,Integer):=table()
v:=[8,6,4,2,3,5,7,9,1]              -- numeri da controllare in quell'ordine di apparizione di v
z:=[k for k in 1..46|prime?(k)]     -- 14 numeri primi da associare a s
F(x,y)==>for i in 1..#x repeat y 
F(z,e.(s.i):=z.i)                   -- riempie la tavola associando numeri primi alle lettere "GXUW..."
t:=[1787026,2451,16445,5957,16036207,130169,20372239,495349,20677]  -- prodotto di numeri primi 1787026 dovrebbe essere HEIGHT
h(a)==
     r:=1 ;F(a,r:=r*e.(a.i))        -- calcola il numero associato alla stringa a
     j:=[];F(v,while r rem z.i=0 repeat(r:=r quo t.i;j:=cons(v.i,j)));j:=sort j  -- leva il nome dei numeri che man mano trova, aggiunge a j
     k:=0 ;F(j,k:=k*10+j.i)         -- costruisce il numero decimale k, da j vettore ordinato
     k                              -- ritorna tale numero k
------------------------------------------------------
(8) -> h("IHNEVGENNEISTE")
   (8)  789
                                                    Type: PositiveInteger
RosLuP
fonte