Вимовте цифри


14

Концепція

Запам'ятовування чисел може бути важким. Запам'ятати слово може бути простіше. Для того, щоб запам'ятати великі числа, я створив спосіб вимовляти їх летописом.

Правила

Кожна цифра спочатку замінюється відповідною літерою:

0 => O
1 => I
2 => R
3 => E
4 => A
5 => S
6 => G
7 => T
8 => B
9 => P

Після заміни дві покращені вимови робляться дві:

  • Між двома приголосними Uдодається а.

  • Між двома голосними Nдодається а.

Приклади / тестові приклади

512431 => SIRANENI
834677081 => BENAGUTUTOBI
3141592 => ENINANISUPUR
1234567890 => IRENASUGUTUBUPO
6164817 => GIGABIT

Що неможливо

  • Букви та цифри змішані одним словом
  • Два послідовних приголосних або два послідовні голосні
  • Листи, яких немає у списку вище
  • Інші персонажі

Правила

Мета цього - створити двосторонній перекладач цієї концепції.

  • Ваша програма спочатку повинна зрозуміти сама, чи це переклад з букви в номер або з числа в букву.
  • Він повинен перевірити правильність формування запису.
  • Якщо все правильно, покажіть переклад.
  • Інше, відобразити повідомлення про помилку, нічого, повернути значення фальси або зламати програму.

Деталі

  • Номер / рядок введення можна вводити в будь-якому форматі (stdin, аргумент, ...)
  • Це , тому найкоротша відповідь виграє.
  • Стандартні лазівки заборонені.

11
Не повинно GIGATESTERбути GIGATESUTER?
kamoroso94

5
Зазвичай ми не просимо, щоб запис був "належним чином сформований", оскільки це просто додатковий код без поважних причин (див. Мета-запитання щодо гарних рекомендацій щодо виклику). Крім того, що означає "правильно сформований"?
Okx

9
Якщо потрібна перевірка вводу, слід включити гідну партію тестових випадків недійсних вводів (особливо, лише літерні входи, які майже є дійсними). Я очікую, що це буде фактично основною частиною виклику багатьох мов.
Мартін Ендер

2
Я погоджуюся з @MartinEnder, що вам слід додати кілька тестових випадків для недійсних справ, наприклад AB23; AEI; BB; Z; ACE; giga; !@#$; -123; і т. д. Також, виходячи з правил перевірки, ми можемо перетворити 6164735732 => GIGATESTER, але GIGATESTERпризведе до помилкового значення через ST(два послідовних приголосних). У способі налаштування вашого виклику в даний час основна частина виклику - це перевірка замість конверсії. Я з цим добре, але в цьому випадку валідацію слід визначити трохи краще.
Кевін Кройсейсен

2
Ваша програма спочатку повинна підкреслити самостійно, якщо це переклад з букви в номер або з числа в букву. Тож переклад має бути двостороннім? Попередній текст та тестові приклади пропонують лише цифру на букву
Луїс Мендо

Відповіді:


5

JavaScript (ES6), 130 байт

Вводиться як рядок в обох способах перекладу. Повертає або переклад у вигляді рядка, або falseу випадку невірного введення.

f=(n,k)=>(t=n.replace(/./g,(c,i)=>1/n?(!i|p^(p=27>>c&1)?'':'UN'[p])+s[c]:~(x=s.search(c))?x:'',p=s='OIREASGTBP'),k)?t==k&&n:f(t,n)

Демо


Якщо він не працює ідеально, не публікуйте його.
Okx

Сподіваємось, зараз працює як очікувалося.
Арнольд

... або збої, коли у введенні є зарезервовані символи регулярних виразів. Досі діє, хоча
edc65

2

Japt , 61 59 92 85 84 байт

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

Приймає вхідний сигнал у вигляді рядка для обох операцій і повертає рядок для обох , а також і falseдля недійсних input.Assumes числа входів завжди будуть містити кілька цифр, додайте 1 байти , які замінять з , Un<space>якщо це не діє. Повертається falseдо тестового випадку, GIGATESTERале, згідно з правилами, це має бути недійсним введенням.


V="OIREASGTBP"UÉ?¡VgXÃe"%v"²_i1'NÃe"%V"²_i1'UÃ:!Uè"%v%v|%V%V|[^{V}NU]" ©Ur"N|U" £VaX

Спробуйте: Числа -> Букви чи літери -> Числа


  • 2 4 байти врятували подяку обаракону , який також переконав мене знову взятися за це після того, як я відмовився від нього раніше. Я б хотів, щоб він цього не зробив!
  • 33 26 25 (!) Байтів пожертвували, впроваджуючи швидке виправлення (тобто ще не буде повністю гольф), щоб перевірити дійсність вводу.

Пояснення

(Ще оновлено до останньої версії)

                          :Implicit input of string U.
V="..."                   :Assign the string of letters to variable V, in order.
UÉ                        :Subtract 1 from U, which will give a number (truthy) if the input is a number or NaN (falsey) if the input is a string.
?                         :If it's a number then
¡                         :    Map over the input string, replacing each character (digit) with ...
VgX                       :      the character in string V at index X, the current digit.
à                        :    End mapping.
e                         :    Recursively replace ...
"%v"²                     :      every occurrence of 2 vowels (RegEx) ...
_i1'N                     :      with the current match with an "N" inserted at index 1.
à                        :    End replacement.
e                         :    Another recursive replacement of ...
"%V"²                     :      every occurrence of 2 non-vowel characters (i.e., consonants) ...
_i1'U                     :      with the current match with a "U" inserted at index 1.
à                        :    End replacement.
:                         :Else, if it's a string then
Uè"%v%v|%V%V|[^{V}NU]"    :    Count the number of matches of 2 successive vowels OR 2 successive non-vowels OR any character not in contained in string V plus N & U.
                          :    (The longest part of this code is the fecking input validation!)
?                         :    If that count is greater than 0 then
T                         :       Return 0.
:                              Else
Ur"N|U"                   :        Replace every occurrence of "N" OR "U" in string U with nothing.
£                         :        Map over the string, replacing each character (letter) with ...
VaX                       :         the index of the current character X in string V.
                          :Implicit output of resulting string

Здається, не обробляються недійсні дані, такі якAEI
Emigna

@Emigna: Ах, чортів! Ви б собі уявити, після того, як спочатку спалили перше "Правило", ми подумали б прочитати решту правил! : \ Я взяв розділ "Що неможливо", щоб зрозуміти, що нам не доведеться обробляти жоден із цих моментів. Невдовзі виправлення.
Кудлатий


1

Java (OpenJDK 8) , 416 410 399 382 376 370 байт

-2 байти завдяки @Cyoce

-17 більше байтів завдяки ідеї @Cyoce

-6 байт завдяки @KevinCruijssen

s->{String c="[RSGTBP]",v="[OIEA]",o="([256789])",e="([0134])";boolean b=s.matches("(c$|v$|(c|vN)(?=v)|(cU|v)(?=c))+".replace("c",c).replace("v",v));int i=-1;for(s=b?s.replaceAll("[UN]",""):s.matches("[0-9]+")?s.replaceAll(e+"(?="+e+")","$1N").replaceAll(o+"(?="+o+")","$1U"):i/0+"";i<9;s=b?s.replace(v,c):s.replace(c,v)){c=++i+"";v="OIREASGTBP".charAt(i)+"";}return s;}

Спробуйте в Інтернеті!

Фу, заміна Java настільки багатослівна.

Функція, яка приймає рядок і повертає рядок, перекладений з числа -> літера або навпаки. Збій на недійсному введенні (ви можете побачити це на прикладі tio, де він виводить правильні значення для перших 10 тестових випадків, а потім виходить з ладу з помилкою поділу на нуль, що відображається у поданні налагодження)

Ungolfed (перший і останній термін циклу for витягується для читабельності)

s-> {
    String c="[RSGTBP]", v="[OIEA]", o="([256789])", e="([0134])"; 
    boolean b=s.matches("(c$|v$|(c|vN)(?=v)|(cU|v)(?=c))+".replace("c",c).replace("v",v)); // lovely regex, explained below
    int i=-1;
    s= b? 
        s.replaceAll("[UN]",""); // remove N's and U's
        :s.matches("[0-9]+")?
        s.replaceAll(e+"(?="+e+")","$1N").replaceAll(o+"(?="+o+")","$1U"); // add N's and U's for separating vowels and consonants
        :i/0+""; // throw an error, looks like a sting for the ternary
    for(;i<9;) { 
        c=++i+"";
        v="OIREASGTBP".charAt(i)+"";
        s=b?s.replace(v,c):s.replace(c,v); // if it started with numbers, go to letters, or vice versa
    }
    return s;
}

Регекс для зіставлення чисел простий, але ось регулярний вираз для відповідності букв до цифр

(c$|v$|(c|vN)(?=v)|(cU|v)(?=c))+
(                             )+   every part of the word is
 c$                                a consonant at the end of the word
   |v$                             or a vowel at the end of the word
      |(c|vN)(?=v)                 or a consonant or a vowel + N followed by a vowel
                  |(cU|v)(?=c)     or a consonant + U or a vowel followed by a consonant


with c = [RSGTBP] and v = [OIEA]

Не те, що це значно покращує ваш масивний байт, але ви можете видалити круглі дужки навколо(s)->
Cyoce

@Cyoce кожен байт допомагає
PunPun1000

оскільки всі ваші гілки ifоператора - це призначення (які повертають значення), спробуйте замінити if... else if... elseна умовний оператор ?:, попередньо Object _=встановивши його, щоб зробити його дійсним. Не впевнений, чи справді це допоможе підрахунку байтів, але я думаю, що це буде.
Кіос

Дві маленькі речі, на яких можна покататись. Ви можете видалити рядок t, оскільки ви використовуєте її лише один раз. Так t.charAt(i)+""стає "OIREASGTBP".charAt(i)+""( -4 байти ). І ви можете розмістити останній рядок всередині for-loop після i<9;внутрішньої заяви for-loop. Так стає for(;i<9;s=b?s.replace(v,c):s.replace(c,v)){( -1 байт ). О, і ви можете поставити те, s=b?...що надходить відразу після int i=-1;внутрішньої петлі for-циклу: for(s=b?...;i<9;...( -1 байт ).
Кевін Кройсейсен

1

PHP; 129 127 267 259 228 байт

$l=IOREASGTBP;$n=1023456789;ctype_digit($s=$argn)?:$s=preg_replace("#U|N#","",strtr($o=$s,$l,$n));for($r=$c=($t=strtr($s,$n,$l))[$i++];$d=$t[$i++];)$r.=((trim($c,AEIO)xor$x=trim($d,AEIO))?X:UN[!$x]).$c=$d;echo$o?$o==$r?$s:"":$r;

Запустіть як трубу -nRабо спробуйте в Інтернеті .

зламатися

$l=IOREASGTBP;$n=1023456789;
# if not digits, translate letters to digits and remember original
ctype_digit($s=$argn)?:$s=preg_replace("#U|N#","",strtr($o=$s,$l,$n));
# translate digits to letters:
for($r=$c=($t=strtr($s,$n,$l))                      # result = first letter
    [$i++];$d=$t[$i++];)                            # loop through letters
    $r.=((trim($c,AEIO)xor$x=trim($d,AEIO))?"":UN[!$x]) # append delimiter if needed
        .$c=$d;                                         # append next letter
# 
echo
    $o              # if original was remembered,
        ?$o==$r         # compare original to final result
            ?$s         # if equal, print digits
            :X          # else print X (as error message)
        :$r;        # else print letters

1

Java 8, 312 308 304 301 294 290 байт

s->{String r="",x="([AEIOU])",y="([BGNPRST])",z="0O1I2R3E4A5S6G7T8B9P";for(int c:s.getBytes())r+=c!=78&c!=85?z.charAt((c=z.indexOf(c)+(c<58?1:-1))<0?0:c):"";return s.matches("(("+x+y+")*"+x+"?)|(("+y+x+")*"+y+"?)|\\d*")?r.replaceAll(x+"(?="+x+")","$1N").replaceAll(y+"(?="+y+")","$1U"):"";}

-4 байти (308 → 304) для виправлення помилок (не трапляється часто, що кількість байтів зменшується, коли я виправляю помилку в своєму коді ..: D)

EDIT: Використовується інший підхід, ніж відповідь Java @ @ PunPun1000 спочатку створивши String return у циклі for для символів, а потім використовує більш абстрактний регулярний вираз для перевірки його в терміналі повернення (вхід - це або всі цифри, або ж чергуються задані голосні та приголосні (так що без суміжних голосних чи приголосних).

Пояснення:

Спробуйте тут.

s->{                                   // Method with String parameter and String return-type
  String r="",                         //  Result-String
    x="([AEIOU])",y="([BGNPRST])",     //  Two temp Strings for the validation-regex
    z="0O1I2R3E4A5S6G7T8B9P";          //  And a temp-String for the mapping
  for(int c:s.getBytes())              //  Loop over the characters of the input-String
    r+=                                //   Append to the result-String:
       c!=78&c!=85?                    //    If the character is not 'N' nor 'U':
        z.charAt(                      //     Get the character from the temp-String `z`
         (c=z.indexOf(c)+              //      by getting the character before or after the current character
            +(c<58?1:-1))              //      based on whether it's a digit or not
             <0?0:c)                   //      and a 0-check to prevent errors on incorrect input like '!@#'
       :                               //    Else:
        "";                            //     Append nothing
                                       //  End of loop (implicit / single-line body)
  return s.matches("(("+x+y+")*"+x+"?)|(("+y+x+")*"+y+"?)|\\d*")?
                                       //  If the input is valid
                                       //  (Only containing the vowels and consonants of `x` and `y`, without any adjacent ones. Or only containing digits)
    r                                  //   Return the result
     .replaceAll(x+"(?="+x+")","$1N")  //    after we've added 'N's if necessary
     .replaceAll(y+"(?="+y+")","$1U")  //    and 'U's if necessary
   :"";                                //  Or return an Empty String if invalid
}                                      // End of method

Регекс перевірки:

(([AEIOU][BGNPRST])*[AEIOU]?)|(([BGNPRST][AEIOU])*[BGNPRST]?)|\\d*


0

Bash ,241 238 235 байт

q=OIREASGTBP;[[ $1 == +([0-9]) ]]&&(x=`tr 0-9 $q<<<$1`;m={B,G,P,R,S,T};n={A,E,I,O};for i in `eval echo $m$m$n$n`;{ a=${i::1};b=${i:1:1};x=${x//$a$b/$a'U'$b};a=${i:2:1};b=${i:3:1};x=${x//$a$b/$a'N'$b};};echo $x)||tr $q 0-9<<<$1|tr -d UN

Спробуйте в Інтернеті!

Менше гольфу:

q=OIREASGTBP;                          save string in q
[[ $1 == +([0-9]) ]]&&(                if argument 1 is only digits
x=`tr 0-9 $q<<<$1`;                    save in x each digit translated to corresponding letter
m={B,G,P,R,S,T};
n={A,E,I,O};
for i in `eval echo $m$m$n$n`;{        generates all combinations of vowels and consonants
                                       BBAA BBAE ... TTOI TTOO
   a=${i::1};                          saves first consonant in a
   b=${i:1:1};                         saves second consonant in b
   x=${x//$a$b/$a'U'$b};               insets U between consonants
   a=${i:2:1};                         saves first vowel in a
   b=${i:3:1};                         saves second vowel in b
   x=${x//$a$b/$a'N'$b};               inserts N between vowels
};
echo $x                               echoes result
)||                                   if argument contains letters
  tr $q 0-9<<<$1|tr -d UN             translates letter to corresponding number and deletes U and N


0

Perl, 127 байт

126 байт + 1 байт командного рядка

$i="AEIOU]";$;=OIREASGTBP;1/!/[^$;NU\d]|[$i{2}|[^\d$i{2}/;eval"y/0-9$;NU/$;0-9/d";s/[$i\K(?=[$i)/N/g;s/[^N\d$i\K(?=[^\d$i)/U/g

Використання:

 echo -n "512431" | perl -p entry.pl

Слід дотримуватися всіх правил виклику - може приймати літери чи цифри і буде помилкою (діленням на нуль), якщо перевірка не вдасться


Перевірка має помилкові позитиви на вході NOта US.
Значення чорнила

0

Ruby , 205 + 1 = 206 байт

Використовує -pпрапор для +1 байта. Тепер із вичерпною системою перевірки вводу.

d,w=%w"0-9 OIREASGTBP"
~/^\d+$/?($_.tr!d,w
gsub /([#{a='AEIO])(?=\g<1>)'}/,'\0N'
gsub /([^#{a}/,'\0U'):(+~/^(([AEIO])(N(?=[AEIO])|(?=\g<4>)|$)|([RSGTBP])(U(?=\g<4>)|(?=\g<2>|$)))+$/;$_.tr!("NU","").tr!w,d)

Спробуйте в Інтернеті!


Це, здається, не перетворює букви в цифри, а також не робить перевірку!
Jarmex

@Jarmex на жаль, додано перевірку! Це величезна перевірка валідації, але у мене немає великого вибору в цьому питанні
Value Ink

0

Пітон 3, 741 байт

from functools import reduce;c=0;e="";n="NU";v="AEIOU";l="OIREASGTBPNU";x=('0','O'),('1','I'),('2','R'),('3','E'),('4','A'),('5','S'),('6','G'),('7','T'),('8','B'),('9','P');s=input()
try:
    int(s);y=reduce(lambda a,kv:a.replace(*kv),x,s)
    for i in y:
        e+=i
        if i in v:
            z=True
            try:
                if y[c+1] in v:e+="N"
            except:
                pass
        else:
            z=False
            try: 
                if not y[c+1] in v:e+="U"
            except:
                pass
        c+=1
except:
    for i in s:
        if not i in l:
            p
    y=reduce(lambda a,kv:a.replace(*kv[::-1]),x,s)
    for i in y: 
        if not i in n:e+=i
print(e)

Спробуйте в Інтернеті!

Є багато можливостей для вдосконалення, я знаю.


0

sed, 123 байт

s/[0134]/_&_/g
s/[25-9]/=&=/g
ta
y/OIREASGTBPU/0123456789N/
s/N//g
q
:a
s/__/N/g
s/==/U/g
y/0123456789_/OIREASGTBP=/
s/=//g

Пояснення

По-перше, ми оточуємо цифри за допомогою _(для голосних) або= (для приголосних).

Якщо ми не проводили жодних підстановок, ми перетворюємо букви в цифри, тож це проста заміна і видаляємо U і N. Тоді киньте.

В іншому випадку ми відкладаємось до мітки a, де ми маємо справу з послідовними голосними, а потім послідовними приголосними. Потім перетворіть цифри в літери та видаліть символи маркера, які ми ввели на першому кроці.


0

Python3, 246 байт

v=lambda x:x in"AEIO"
V="OIREASGTBP"
i=input()
r=__import__("functools").reduce
print(r(lambda x,y:x+(("U",""),("","N"))[v(x[-1])][v(y)]+y,map(lambda x:V[x],map(int,i)))if i.isdigit()else r(lambda x,y:x*10+V.index(y),filter(lambda x:x in V,i),0))    

пояснення:

  • введення карти до списку int
  • відобразити список int до їх положення в алфавіті
  • зменшити список, додавши акумулятор, плюс елемент dict кортежу плюс поточний елемент
    • Диктує Кортеж таблиця істинності заснована на двох елементах, будучи гласним чи ні

0

JavaScript (ES6), 120

Функція, що приймає введення як рядок. Він повертає правильно перекладений рядок, якщо введення є дійсним, інакше помилковим або функція завершується.

n=>(t=n=>n.replace(/./g,d=>1/d?(v-(v=d<5&d!=2)?'':'UN'[v])+z[d]:~(a=z.search(d))?a:'',v=2,z='OIREASGTBP'))(q=t(n))==n&&q

Менше гольфу

n => 
{
  var t = n => { // function to translate, no check for invalid input
    var v = 2; // 1 = digit map to vowel, 0 = digit map to consonant, start with 2
    var z = 'OIREASGTBP'; // digits mapping
    return n.replace(/./g,
      d => 1/d // digit / alpha check
        ? ( // if digit
            w = v, // save previous value of v
            v = d < 5 & d != 2, // check if current digit will map to wovel or consonant
            (w != v 
             ? '' // if different - wovel+consonant or consonant+wovel or start of input
             : 'UN'[v] // if equal, insert required separator
            ) + z[d] // add digit translation
          )
        : ( // if alpha
             a = z.search(d), // look for original digit. Could crash if d is a reserved regexp char (not valid input)
             a != -1 ? a : '' // if digit found add to output, else do nothing
          )
    )
  }

  var q = t(n); // translate input an put in q
  if (t(q) == n) // translate again, result must be == to original input
    return q; // if ok return result
  else
    return false; // else return false
}

Тест

var F=
n=>(t=n=>n.replace(/./g,d=>1/d?(v-(v=d<5&d!=2)?'':'UN'[v])+z[d]:~(a=z.search(d))?a:'',v=2,z='OIREASGTBP'))(q=t(n))==n&&q

;`512431 => SIRANENI
834677081 => BENAGUTUTOBI
3141592 => ENINANISUPUR
1234567890 => IRENASUGUTUBUPO
6164817 => GIGABIT`
.split('\n')
.forEach(x => {
  var [a,b] = x.match(/\w+/g)
  var ta = F(a)
  var tb = F(b)
  console.log(a==tb ? 'OK':'KO', a + ' => '+ ta)
  console.log(b==ta ? 'OK':'KO', b + ' => '+ tb)
})

function go() {
  O.textContent = F(I.value)
}

go()
<input id=I value='NUNS' oninput='go()'>
<pre id=O></pre>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.