Оригинальный номер (II)

18

Эта задача, по сути, идентична этой, только с одним отличием: теперь разрешено перетасовывать буквы в любом месте строки.

сценарий

У Джона есть важный номер, и он не хочет, чтобы другие видели это.

Он решил зашифровать номер, используя следующие шаги:

Его число всегда является неубывающей последовательностью (т. Е. "1123")

Он перевел каждую цифру в английские слова. (т.е. "123" -> "ONETWOTHREE")

А затем переставить буквы случайным образом. (т.е. "ONETWOTHREE" -> "EEWOOHRNTET")

Джон чувствовал, что его номер был в безопасности при этом. На самом деле, такое шифрование может быть легко расшифровано :(


задача

Учитывая зашифрованную строку s, ваша задача расшифровать ее и вернуть исходный номер.


правила

  • Это код гольф, поэтому самый короткий ответ в байтах выигрывает
  • Вы можете предположить, что входная строка всегда действительна
  • Входная строка содержит только заглавные буквы
  • Оригинальные номера всегда располагаются в порядке возрастания
  • Вы можете вернуть число в строковом или целочисленном формате
  • Буквы будут перетасовываться только между одним словом, а не между всей строкой. Буквы могут быть перемешаны в любом месте строки.
  • Числа будут только от 1 до 9 включительно ( ONEдо NINE)

Возможная расшифрованная строка

Вот список строк сразу после того, как они были преобразованы в строки из чисел:

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

Примеры

"NEO" -> 1

"NWEOOT" -> 12

"TOEERWNEHOT" -> 123

"IHNEVGENNEISTE" -> 789

"WEETVTRFSVUHNEEFRHIXEOINSNIEGTOONIEE" -> 123456789

"EWHEWROETOTTON" -> 1223

"ONEWESTV" -> 27 (спасибо, ETHпродукция!)

Кристиан Лупаску
источник
7
Предлагаемый тестовый пример: что-то вроде "ONEWESTV" -> 27(включает число, которое на самом деле не появляется)
ETHproductions
@ETHproductions Отличная идея! Добавлен.
Кристиан Лупаску,
Почему нет "НУЛЯ"?
Рослуп
@RosLuP Джон ненавидит ведущие нули ...
Кристиан Лупаску

Ответы:

9

Python 2 , 123 байта

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

Полная программа, принимающая введенные данные и печатающая номер Джона.

Попробуйте онлайн! или увидеть тестовый набор

Как?

Давайте работать с примером "NEONSEXTOWNII" (чтобы получить 1269, и быть несколько Leisure Suite Larry -esque!)

Сначала c=map(input().count,"OWHUFXSGIQ")берется ввод и подсчитывается число каждого из них OWHUFXSGIQ- это буквы, которые появляются в каждом номере в порядке возрастания, где 2,4,6 и 8 имеют свои «собственные» буквы ( WUXG) плюс лишняя буква, Qчтобы добавить ноль до конца и выровняйте длину полученного списка. Для примера:

[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

Записи для 1, 3, 5, 7 и 9 нуждаются в корректировке, чтобы исправить количество других букв. Это выполняется следующим циклом:

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

Обратите внимание, что записи для корректировки являются альтернативными (1,3,5,7,9,1,3,5, ...), поэтому мы можем добавить два к индексной переменной на каждом шаге и по модулю на 10, чтобы остаться в диапазон, если нам нужно пройти более одного раза (что мы делаем). Чтобы сэкономить несколько байтов, мы можем увеличить на единицу и по модулю на 5 и использовать двойной индекс.
Поскольку корректировки для 9 требуют большей работы, которую мы начинаем там - она ​​находится в индексе 8, поэтому мы начинаем с i=4. Затем строка "71735539994"дает индексы jзначений, которые нужно удалить на каждом этапе (где мы убедились, что девятый индекс будет содержать ноль при использовании "Q"при создании c); c[i*2]-=c[int(j)]выполняет каждую отдельную корректировку и i=-~i%5переходит iк следующему индексу (где -~iесть -(-1-i)или i+1сохранение скобок (i+1)%5), сохраняяi*2в пределах c.
Таким образом, мы сначала вычитаем число в индексе j=7из числа в индексе i*2=8, вычитая количество «G», подсчитанное из числа «I», корректируя счет «NINE» вниз на (правильное) число «EIGHT» s ( который также имеет "я"). Затем мы переходим на i=0( -~4%5 = (4+1)%5 = 0), ссылаясь на индекс, i*2 = 0который предназначен для «ОДИН», и вычитаем значение, найденное в индексе j=1записи, считая «W» и, следовательно, «ДВА», корректируя счет «О» вниз. К концу цикла у нас есть исправленные значения:

[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

так что все, что осталось, это распечатать то, что cсейчас представляет ( 1269). iтеперь вернулся в 0, поэтому мы увеличиваем его в начале цикла и используем в качестве нашей цифры:

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

Задние тиков, `i`являются python2 стенография для repr(i)которых получает строковое представление объекта (цифра символа в вопросе в виде строки) и умножения строки на целый ряд Creats новую строку , что многие повторы (здесь мы показываем только n=0поворот `i`от Say "5"к ""и n=1превращение, скажем, "6"как "6", но это также работает для больших положительных целых чисел, так "3"*4становится, "3333"например.)

Джонатан Аллан
источник
8

05AB1E , 31 байт

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

Попробуйте онлайн!

объяснение

[                                   # 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

Очень неэффективно для большого ввода.

Emigna
источник
‘Z€µ‚•„í†ìˆÈŒšï¿Ÿ¯¥Š‘# # push the list ['Z','ONE','TWO','THREE','FOUR','FIVE','SIX','SEVEN','EIGHT','NINE']Можете ли вы объяснить немного, я изо всех сил пытаюсь понять, как можно генерировать любую строку.
Кирилл Гандон
1
@CyrilGandon: ограничивает сжатую в верхнем регистре строку слов, разделенных пробелом. Zзначит Z. Все остальные пары из двух символов обозначают сжатое слово из словаря 05AB1E . Так например €µпереводится как ONE.
Эминья
Хорошо, как вы сжимаете строку, содержащуюся в словаре? Что-то со значением Unicode для пары?
Кирилл Гандон
1
@CyrilGandon: Вы берете номер строки слова в dict (2420 для привет ) и вычитаете 1. Это дает нам 2419. Символы, которые нам нужны, это символы, за которыми следуют 24и 19в документах . В нашем случае это 24=Ÿи 19=™так HELLOбудет‘Ÿ™‘
Emigna
1
Существует также компрессор, написанный Аднаном, который вы можете использовать в большинстве случаев. Ссылка немного длинная, но вы можете найти ее в чате 05AB1E . Это также хорошее место, чтобы спросить, если у вас есть еще вопросы :)
Emigna
8

Сетчатка , 112 97 байт

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`.

Попробуйте онлайн!

-12 байт благодаря @Neil

-3 байта за счет использования L символьных классов в транспозиции

Как это устроено

По сути, это зависит от того факта, что буквы используются только в определенных числовых именах. Например, SIXэто единственное имя, которое содержит X. Это становится сложнее с тем фактом, что некоторые слова накладываются друг на друга, например, оба FIVEи SEVENиспользование V. Это можно исправить путем идентификации FIVEс F(.*)V.

fireflame241
источник
1
@RickHitchcock Исправлено. Рекурсия по конвертации в 8 не работала должным образом
fireflame241
1
@RickHitchcock. Исправлена ​​рекурсия для всех из них.
fireflame241
Раздражающе GHи NOбыло бы рядом, за исключением любой предыдущей 8или 1от предыдущей замены ...
Нил
Возможно , }`GH 8будет работать 8- }бы вызвать символы , которые будут отсортированы снова, таким образом , размещая все оставшиеся Gи Hвместе.
Нил
@Neil Хорошая идея. Я также смог сделать это NO -> 1, что было удобно.
fireflame241
5

Котлин 1,1 , 359 352 331 327 325 байт

представление

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}

Не работает на TryItOnline из-за того, что Kotlin 1.1 не поддерживается

Тестовое задание

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")
        }
    }
}

логика

Шпаргалка

Я использовал лист выше, чтобы выработать самый простой способ решить каждую букву

  • Зеленый = Решить сам
  • Синий = Требуется зелень, чтобы решить
  • Оранжевый = Нужен блюз для решения
  • Красный = нужно апельсины для решения

Правки

  • -7 - Пробелы изменяются на w0lf
  • -21 - Сокращенный список для массива
  • -4 - убраны лишние скобки
  • 0 - добавлена ​​логика в
  • -2 - Повторное использование пустой строки благодаря kevin-cruijssen
jrtapsell
источник
1
Просто заметил, что я точно связан с вами своим ответом Java 8 (127 байт), используя аналогичный подход. ;) Но один вопрос: вы не можете изменить var s=""и return sк r=""и return rпутем повторного ввода-String, вам больше не нужно , которые в этот момент? Я никогда раньше не программировал в Котлине, так что, может быть, я здесь чушь несуразная. ; p
Кевин Круйссен
1
К сожалению, не> обсуждать.kotlinlang.org
t/
1
Ах да, это, конечно, было возможно; параметры finalпо умолчанию. Хм, еще одна вещь, которую вы могли бы сыграть в гольф: поместите в var s=""качестве первой вещи в методе и замените val f=r.split("").на val f=r.split(s).. Опять же, не знаю, работает ли это. Жаль, что TIO еще не поддерживает v1.1, иначе я бы сам попробовал эти предложения, прежде чем казаться глупым ..
Кевин Круйссен
4

Желе , 37 байт

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

Попробуйте онлайн!

-1 спасибо Джонатану Аллану .

Эрик Outgolfer
источник
Это время ожидания для некоторых входов больше 7 символов (например NINEFIVE, THREEFIVE). Это ошибка или код просто неэффективен?
Кристиан Лупаску
@ w0lf последний ( Œ!означает «перестановки»)
Эрик Outgolfer
Сохраните байт, используя «AA» вместо «!»:...“©ȯ¿w¶&ÇhṆỌƘ#Ȯʋ~¢CNẓ_»...
Джонатан Аллан
@JonathanAllan О, АА это слово?
Эрик Outgolfer
Это первое слово в кратком словаре, да.
Джонатан Аллан
3

Java 8, 248 234 байта

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;}

Объяснение кода:

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 Благодаря Оливье Грегуару

Edwardth
источник
1
234 байта
Оливье Грегуар
2

Java 8, 346 345 344 336 327 байт

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;}

Попробуй это здесь.

Общее объяснение:

Я посмотрел на вхождения каждого символа в алфавите:

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
  • Я первый подсчитаны все вхождения символов Однополочных матчей: G=8; U=4; W=2; X=6.
  • Тогда все вхождения двух совпавших символов, которые также соответствуют одному из четырех выше, что я могу вычитать из их подсчетов: F=5; H=3.
  • Затем я снова сделал то же самое для V=7(вычитая F=5).
  • Тогда же для всех трех-матчей символов , которые были оставлены: O=1; N=9.
    • Но поскольку в нем Nесть два вхождения NINE, мне приходилось делать дополнительные -1для каждого вхождения N, поэтому я использовал I=9вместо этого (вычитая три предыдущих совпадения вместо двух).

Объяснение кода:

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)
Кевин Круйссен
источник
1
Блин, я бы подумал, что добавление в список, а затем сортировка будет короче (это не так). Отлично сработано!
Оливье Грегуар
1
Ну, в конце концов, я перехитрил тебя , но ненамного;)
Оливье Грегуар
1

Python 3 , 225 байт

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)))

Попробуйте онлайн!

Просто: сначала удалите цифры, которые обозначены конкретной буквой.

jferard
источник
1

Python 3 , 125 байт

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())

Попробуйте онлайн!

Прочитав связанный вопрос, я понял, что это вариант решения Python от mdahmoune , которое само основано на решении ES6 Draco18s , но, по крайней мере, мы проиграли два байта.

Подобно этому решению, мы вычисляем ответ через линейную комбинацию количества вхождений определенных букв. Мы кратко кодируем линейные комбинации, записывая их в виде слов, в которые должны быть добавлены первые две буквы, а затем все вычтено. Иногда требуется символ для дополнения первых двух символов; мы используем это, чтобы скрыть цифру, которую мы хотим вывести (которая никогда не появится на входе, поэтому не повлияет на наш алгоритм), которую мы извлекаем min.

betaveros
источник
1

Аксиома, 351 байт

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)

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
источник