Отображение между целым и произносимым словом

10

Цель

Идея состоит в том, чтобы предоставить код, необходимый для отображения 32-разрядного целого числа в / из произносимого слова максимум из 9 символов. Это может быть полезно, например, для облегчения запоминания серийного номера или ввода формы.

Требуется как способ перевода целого числа в соответствующее слово, так и обратного перевода слова в соответствующее целое число.

правила

Между целыми числами и словами должно быть взаимно-однозначное соответствие, и весь набор 32-разрядных целых чисел (или, другими словами, любое целое число от 0 до 4294967295) должен быть отображаемым. Хотя, очевидно, не все слова будут значимыми, и ввод слов, которые не отображаются в целое число, может иметь неопределенное поведение.

Вы можете сами выбирать, какой именно набор «произнесенных» слов имеет смысл, и как выполняется сопоставление, но слова должны, по крайней мере, следовать этим правилам:

  • Только основные 26 букв (A ... Z) должны использоваться в качестве символов. Акценты, корпус и т. Д. Не должны использоваться для расширения возможных комбинаций.
  • Максимум 9 символов на слово.
  • две согласные (BCDFGHJKLMNPQRSTVWXZ - 20 возможностей) не должны быть расположены рядом друг с другом (они должны быть окружены гласными).
  • две гласные (AEIOUY - 6 вариантов) не должны находиться рядом друг с другом (они должны быть окружены согласными).

Примечание. Самая простая схема, в которой все слова построены как CVCVCVCVC( Cбудучи согласным и Vгласным), дает 4147200000 комбинаций, а 32-разрядное целое число имеет 4294967296 возможных значений, поэтому этого недостаточно. Вам необходимо увеличить количество комбинаций, либо добавив более короткие слова, либо добавив также VCVCVCVCVкомбинации.

Применяются другие стандартные правила, а стандартные лазейки запрещены.

Входы / выходы

Для каждого представления должны быть предоставлены две части кода:

  • Тот, который принимает целое число в качестве аргумента / ввода и возвращает / печатает соответствующее слово
  • Тот, который принимает слово в качестве аргумента / ввода и возвращает / печатает соответствующее целое число

Кроме того, вы можете отправить один фрагмент кода, который обрабатывает обе операции:

  • Когда в качестве входных данных задано целое число, оно выводит соответствующее слово
  • Когда в качестве входных данных приводится строка, она выводит соответствующее целое число

Выигрышное условие

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

тусклый
источник
Есть ли ограничения по времени или пространству? Должны ли мы умещаться в пределах 32 ГБ памяти?
Джон Дворак
@JanDvorak Ну, у нас должна быть возможность протестировать вашу программу на «стандартном» компьютере. Но алгоритм должен быть простым, что вы имеете в виду, что требует такого огромного количества памяти?
тусклая
Я мог бы просто сгенерировать все возможные девятибуквенные слова, которые соответствуют вашей формуле, и затем включить их в набор или выполнить бинарный поиск.
Джон Дворак
@JanDvorak Я должен признать, что я не думал об этом. Я больше думал о решениях, которые в основном делали преобразования base-26, с некоторыми корректировками, чтобы удовлетворить ограничение гласных / согласных. Но я почему-то сомневаюсь, что "зверский" способ, которым вы имели в виду, может быть эффективным в код-гольфе. В любом случае, если я действительно должен уточнить это, скажем, вам не разрешено выделять более 4 ГБ памяти.
тусклый
Вы можете потребовать, чтобы ответчики запустили свой код для некоторых предопределенных значений (0,1,10,2 ** 32-1 и т. Д.), А затем вернулись и включили результаты в ответ.
Джон Дворак

Ответы:

1

JavaScript (ES6), 205 байт

p=>(a='bcdfghjklmnpqrstvwxzaeiouy',1/p)?[...Array(9)].map(_=>r=a[p%(n=26-n)+(p=p/n|0,n<7)*20]+r,n=p>(p%=4e9)?20:6,r='')&&r:[...p].map(c=>r=r*(n=26-n)+a.search(c)%20,n=a.search(p[r=0])<20?6:20)&&r+(n<7)*4e9

Точка среза между CVCVCVCVC и VCVCVCVCV равна 4e9, поэтому начинается ошибка 5244160000 (числовой ввод) или zesuwurib(строковый ввод).

Нил
источник
Шесть месяцев спустя ... Я присуждаю вам баллы за принятие, так как вы самый короткий (и я не могу принять ответ rturnbull, который не удовлетворяет разъяснениям, которые я сделал в комментариях).
тусклый
2

PHP, 353 байта

Кодировка + Декодирование

is_numeric($argn)содержит логическое значение. Это правда, если ввод является целым числом.

$c=array_diff(range(A,Z),$v=[A,E,I,O,U,Y]);sort($c);if(is_numeric($a=$argn)){$r=($a)%26<6?$v[$a%26]:$c[$a%26-6];$a=$a/26^0;while($a){$z=count($t=in_array($r[0],$v)?$c:$v);$r=$t[$n=$a%$z].$r;$a=$a/$z^0;}echo$r;}else{for($p=1;$i++<strlen($a);){$u=($b=in_array($a[-$i],$c))?$c:$v;$s+=array_flip($u)[$a[-$i]]*$p+($b&$i<2?6:0);$p*=$i>1?count($u):26;}echo$s;}

PHP, 190 байт (кодирование) + 195 байт (декодирование) = 385 байт

кодирование

$c=array_diff(range(A,Z),$v=[A,E,I,O,U,Y]);sort($c);$r=($a=$argn)%26<6?$v[$a%26]:$c[$a%26-6];$a=$a/26^0;while($a){$z=count($t=in_array($r[0],$v)?$c:$v);$r=$t[$n=$a%$z].$r;$a=$a/$z^0;}echo$r;

5391360000 = 26 * 120 ** Доступны 4 комбинации

Кодирование онлайн-версии без E_NOTICE

расширенный

$c=array_diff(range(A,Z),$v=[A,E,I,O,U,Y]);
sort($c); # End of Prepare the two array
$r=($a=$argn)%26<6?$v[$a%26]:$c[$a%26-6]; #base 26 decision input mod 26 <6 end with vowel
$a=$a/26^0; #integer division input with 26
while($a){
    $z=count($t=in_array($r[0],$v)?$c:$v); # use vowel if last entry is consonant and viceversa
    $r=$t[$n=$a%$z].$r; # base 6 or base 20 decision
    $a=$a/$z^0; # divide through base
}echo$r; # Output result

Вход => Выход

4294967296 => TYPYQACOV 
333 => DAT 
1 => E 
7 => C 
4294967276 => UTOPOQAMI

Если вам нужен всегда 9-байтный результат, пожалуйста, замените while($a)на while(strlen($r)<9)+ 10 байт

Декодирование

$c=array_diff(range(A,Z),$v=[A,E,I,O,U,Y]);sort($c);for($p=1;$i++<strlen($a=$argn);){$u=($b=in_array($a[-$i],$c))?$c:$v;$s+=array_flip($u)[$a[-$i]]*$p+($b&$i<2?6:0);$p*=$i>1?count($u):26;}echo$s;

расширенный

$c=array_diff(range("A","Z"),$v=["A","E","I","O","U","Y"]);
sort($c); # End of Prepare the two array
for($p=1;$i++<strlen($a=$argn);){ 
    $u=($b=in_array($a[-$i],$c))?$c:$v; # find use array for $a[-$i]
    $s+=array_flip($u)[$a[-$i]]*$p+($b&$i<2?6:0); # sum value
    $p*=$i>1?count($u):26; # raise multiple for next item
}echo$s;

Вход => Выход

ABABABABE => 1
E => 1
UTOPOQAMI => 4294967276
BABABADAT => 333
DAT => 333
TYPYQACOV => 4294967296

Декодирование онлайн-версии без E_NOTICE

Дополнительная проверка

Если нам нужна проверка, если строка действительна.

Добавьте $x.=$b?:0;в конец цикла декодирования + 10 байт.

Заменить echo$s;на echo!preg_match('#([01])\1$#',$x)?$s:_;+ 32 байта

Йорг Хюльсерманн
источник
1

R 165 байт

Кодирование и декодирование в одной функции.

Эта функция использует метод грубой силы для создания всех возможных значений, а затем просто возвращает индекс, когда ему вводится строка, и возвращает строку, когда вводится целое число. Как следствие, это очень медленно и использует 16 ГБ + памяти!

function(x){i=c(1,5,9,15,21,25)
d=apply(expand.grid(c<-letters[-i],v<-letters[i],c,v,c,v,c,v,c(c,"")),1,paste,collapse="")
`if`(mode(x)=="numeric",d[x],which(d==x))}

Возможны 4 354 560 000 значений. Это охватывает все строки формы CVCVCVCV (C), причем последний C является необязательным.

rturnbull
источник
@ mbomb007 Гигабайт, извините за опечатку. Функция выполняет как кодирование, так и декодирование в зависимости от того, является ли аргумент строкой или целым числом. Я обновил пост, чтобы уточнить это.
rturnbull
Может ли downvoter оставить комментарий, чтобы предложить улучшение? Спасибо.
rturnbull
1
В комментариях к вопросу Дим поясняет, что вы не можете использовать более 4 ГБ памяти ....
Сократов Феникс