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


36

Руководящие указания

сценарий

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

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

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

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

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

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


задача

Учитывая зашифрованную строку 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

"ENOWOT" -> 12

"EONOTWHTERE" -> 123

"SNVEEGHEITNEIN" -> 789

"ENOOWTEERHTRUOFEVIFXISNEVESTHGIEENIN" -> 123456789

"NOEWOTTOWHEERT" -> 1223


5
Во всех тестовых случаях перемешиваются только буквы в слове, а не буквы между словами. Всегда ли так будет?
xnor

1
@xnor Это всегда будет так. Я отредактировал вопрос.
Аморрис

1
тогда вам нужно изменить это ".... (то есть." ONETWOTHREE "->" TTONWOHREEE ")"
J42161217

2
@ TessellatingHeckler: не строго возрастающая последовательность - это когда следующее число может совпадать с предыдущим. 1-1-1-2-2-3 (не строго увеличивается), в отличие от 1-2-3-4-5 (строго увеличивается)
koita_pisw_sou

1
Технически говоря, это кодировка, а не шифрование, так как нет ключа.
Патрик Робертс

Ответы:


5

Желе ,  38  37 байт

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

Монадическая ссылка, содержащая список символов (строку) и возвращающая целое число.

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

Использует очень отличается метод в желе ответ Pietu1998 в , но имеет тот же счетчик байтов ( я действительно думал , что это , возможно , она в конечном итоге , как меньше)!

Не полагается на монотонность исходного числа (таким образом, ввод HTREEWTONOEбудет работать, например).

Как?

Во-первых, обратите внимание, что все слова (и, следовательно, любые их анаграммы) можно изменить на слова длиной 4, удалив любые буквы R, G и S и заменив любые буквы Os двумя символами (скажем, «12»), а любые буквы X - тремя символами ( скажем "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

Затем мы можем отобразить произведение порядковых чисел этих символов на числа от 1 до 9, используя арифметику по модулю, в зависимости от нашего выбора («12345»), а затем посмотреть их в переупорядоченном списке цифр. Код на самом деле сначала преобразуется в символы, а затем заменяет порядковые номера, но это также возможно в 37 байтах с символами, например, «DIAAE» ( попробуйте ).

ḟ“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

Ваш ответ буквально единственный ответ на этой странице , которая возвращает правильное значение: NINEONENIENOENNNIENOENNEINEONEINEONNENIENOINNEINENINNEINENIENNIENNNNIENNEININENIENNENINEINENINENNIEINNEINNENNIENIN.
Волшебная Урна Осьминога

+ Бесконечные очки.
Волшебная Урна Осьминога

Благодарность! (это бросило меня из-за того, что в блоке кода есть пробелы нулевой ширины в комментарии, но (вот так) это работает )
Джонатан Аллан

В любом случае, это неверный ввод;).
Волшебная Урна Осьминога

Ого, я не знала, что щедрость приближается - спасибо! Да, это не было частью запрошенной спецификации, я просто создал метод, который будет работать с неупорядоченным вводом.
Джонатан Аллан

10

Python 2, 121 117 115 байт

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 байта: после всего этого игры в гольф я забыл встроить переменную одноразового использования. Мозг пердеть.
-2 байта: отступ с двойным интервалом → отступ с одной вкладкой (спасибо Coty Johnathan Saxman); обратите внимание, что это не отображается правильно в ответе.

Ungolfed (совместимо с 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

Поиск магического числа:

#!/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))

Объяснение:

У меня было чувство, что я могу разбить биты ASCII вместе и как-то суммировать, чтобы определить, когда у меня было полное слово. Первоначально я пытался возиться 3**ord(letter)и сравнивать с ожидаемыми результатами, но это привело к очень большим числам. Хотя было бы уместно немного перебрать некоторые параметры, а именно модуль (чтобы гарантировать, что числа малы) и множитель, чтобы по-разному распределить числа по диапазону модуля.

Я закончил тем, что изменил множитель переменной на переменную, влияющую на саму мощность, потому что (методом проб и ошибок), которая каким-то образом смогла дать мне немного более короткий ответ в гольфе.

И выше вы видите результаты этого грубого и небольшого ручного игры в гольф.

Причина выбора 3**xизначально в том, что я знал, что вы можете представить каждое число там. Самые повторяющиеся цифры, которые были у любого числа, равны двум (thrEE, sEvEn, NiNe и т. Д.), Поэтому я решил рассматривать каждый вход как число с номером 3. Таким образом, я мог (мысленно) представить их как что-то вроде 10100000000010020000(три; 1 в tслоте, 1 в rслоте, 1 в hслоте и 2 в eслоте). Таким образом, каждое число получает уникальное представление, которое может быть легко объединено путем итерации строки и суммирования некоторых чисел, и оно заканчивается независимо от фактического порядка букв. Конечно, это не оказалось идеальным решением, но текущее решение все еще написано с учетом этой идеи.


Что такое Py3K? ...
CalculatorFeline

Извинения, отредактировано (это прежнее название python 3)
Score_Under

1
Это дешево, но вы можете сэкономить 2 байта (поскольку это Python 2), добавив второй уровень отступа (два пробела) для одной вкладки. [ tio.run/##NU7NCoJAGDy7T/… Попробуйте онлайн!]
Коти Джонатан Саксман

Кроме того , вы можете быть в состоянии сохранить 6 байт с помощью Литерала \x83, \x8eи \x92в строке.
CalculatorFeline

@CalculatorFeline К сожалению, моему переводчику это не нравится 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. Это работает, если я помещу codingкомментарий там, но это получает 15 дополнительных байтов.
Score_Under

6

Python 2 , 131 127 байт

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

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

На основе исправленной версии решения JavaScript Draco18s .


Какое интересное использование vars!
xnor

@xnor это было ovs, как узнал меня, что для других гольфов :)))
mdahmoune

Очень умно. Имейте +1 за адаптацию моего ответа (так же, как и изначально).
Draco18s

5

PHP , 164 байта

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

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

PHP , 179 байт

на основе предыдущего подхода сначала проверьте четные числа, а затем нечетные числа в порядке возрастания

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

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

PHP , 201 байт

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

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


терпит неудачу дляENOOWTWTOWOT
Тит

@Titus теперь исправлен. Я неправильно понял вопрос
Йорг Хюльсерманн

Да, примеры несколько вводят в заблуждение. Вау, это стоило! Вы сломаете это ?!
Тит

@ Titus Я думаю, что я достиг предела, чтобы найти другой путь, как ваш подход
Йорг Хюльсерманн

1
$i++<9и $iвместо $i<10и ++$i(-1 байт); _405162738[$i]вместо $i%2?$i/2+4:$i/2-1(-4 байта) ( $i/2+~($i%2*-5)тоже будет работать, но это на один байт длиннее.)
Тит

5

Javascript (ES6), 288 150 144 байта

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

Дольше, чем две другие записи из JS, но я подумал, что я бы отказался от интересного подхода, который мог бы работать для кого-то на другом языке.

По сути, мы можем определить следующее:

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

Любое вхождение этих букв подразумевает, что эта цифра существует в исходном номере. Отсюда мы можем вывести остальные цифры:

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

Включая два сложных случая:

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

Как 1и 9область Хард сравнительно. Для ОДНОГО, Eпоявляется несколько раз в некоторых словах ( SEVENимеет два), как делает N( NINE), поэтому мы застряли с проверкой, Oкоторая происходит в двух других местах, к счастью, оба просты.

Для NINE девять сложно, независимо от того, как вы нарезаете.

Таким образом, мы получаем эту карту:

[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 может ссылаться на siX, eiGht и Five (с 5 обратными ссылками) с присвоением переменных, сохраняя байты. Спасибо Нилу за это, он использует несколько функций JS, с которыми я очень незнаком ( ('например, отметки для раздевания пополам) и на самом деле гораздо ближе к идее, которую я набросал на бумаге, прежде чем пытаться ее кодировать. (Я оставил 9 как «то, что осталось», думая об этом как «если я увижу, Xя могу удалить его, а также Sи Iиз строки, то ...», так что после четырех простых случаев следующие 3 станут просто).

Причина, по которой эта запись интересна, заключается в том, что она может обрабатывать любую перетасованную строку как ввод. т. е. вместо того, чтобы перетасовывать отдельные слова, мы можем перетасовать всю строку, что, как я думал, первоначально делал Джон:

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
Отлично, но есть проблема со счетом 9 ... Я думаю, что это может быть ixg-f + u
mdahmoune

@mdahmoune Стреляй, ты прав. Я испортил это. : <
Draco18s

Сохраните 4 байта, используя s.split(t).length-12 байта s.repeat(n>0&&n)(почему в любом случае n меньше нуля? Экономит 7 байтов). Сохраните кучу байтов, объявив их gв области видимости, sчтобы вам не приходилось постоянно передавать его, и, что еще лучше, вы можете сделать его теговым шаблоном, который в целом экономит 55 байтов (до 9 исправлений). Сохранить более байт, сохраняя повторяющиеся значения в временных, и я брился несколько больше от использования 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 Я не уверен, почему N когда-либо оказался меньше нуля, но это было при тестировании на ТРИ. Я продолжал получать сообщение об ошибке и, обнаружив, что это необходимо, но все еще не уверен. В шаблонной карте библиотеки есть JavaScript, который я даже не умею читать. : D
Draco18s

@Neil Ах, да, причина для проверки п> 0: Если есть в две , но не ТРЕТЬЯ. R = 0, W = 1. 0-1 = -1. У меня были проблемы с тем, чтобы выяснить это час назад, я знал, что это было связано с 3-чеком, но у меня был дьявол времени, решающий это (нехватка кофе).
Draco18s

4

Mathematica, 133 байта

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


вход

"VENESGTHIEENNI"

выход

+789


Не могли бы вы сохранить дополнительный байт c@#[[i]]вместо c[#[[i]]]? Вы можете сохранить другой байт, используя синтаксис инфикса ~в Table.
Числовой маньяк

4

C #, 218 байт

Укороченная версия:

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

Расширенная версия:

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

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

Будучи моей первой записью, я не уверен в правилах ... Я рассчитываю только размер класса, используемого для дешифрования, а не код, который его тестирует, верно?

редактировать

И для забавы - вот что я начал делать, не читая полных правил: S - Посмотрите это на IdeOne . Он дешифрует, даже когда символы из одной цифры могут быть скремблированы в любом месте строки.

Редактировать 2

Укорочен в соответствии с советами TheLethalCoder. Благодарность!

Редактировать 3

А теперь Тит побрился еще на несколько байтов. Благодарность!


2
Привет и добро пожаловать в PPCG! Вам нужно только включить метод, который вы можете удалить public staticиз него. Вы можете преобразовать в анонимный метод, как s=>{<do stuff>return"";}. Вы можете использовать varнесколько раз, объявляя переменные вместе сохраняет байт т.е. int i=1,j;. Создание массива из строки и расщепления на нем, как правило , короче (хотя я не проверял , в данном случае) , то есть "ONE|TWO".Split('|'). Вы можете использовать <0вместо==-1
TheLethalCoder

Дополнительные советы см. В разделе Советы по игре в гольф на C # .
TheLethalCoder

@TheLethalCoder Отличные советы, спасибо!
SamWhan

Совсем не проверено, но я считаю, что следующий код эквивалентен вашему коду для 221 байта: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

С другой стороны, обычно проще использовать TIO для ваших TIO!
TheLethalCoder

3

JavaScript (ES6), 142 139 байт

Сохранено 3 байта благодаря Нейлу .

В настоящее время не использует номера всегда расположены в порядке возрастания

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


чего ждать?? "axbxc".split`x`.join``, Как это называется? Не могу найти что-нибудь на Google.
Qwerty

@Qwerty - Это теги литералов шаблонов , особенность ES6, которую я использую, чтобы сэкономить несколько байтов, не нуждаясь в скобках в случае splitиjoin
Крейг Эйр,

Вы ответили на это. Я знаю теги литералов шаблонов, но я не понял, что вы можете использовать их и в этих функциях. Спасибо.
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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.