Ánh xạ giữa số nguyên và từ có thể phát âm


10

Mục đích

Ý tưởng là cung cấp mã cần thiết để ánh xạ một số nguyên 32 bit đến / từ một từ có thể phát âm tối đa 9 ký tự. Điều đó có thể hữu ích, ví dụ, để làm cho số sê-ri dễ nhớ hơn hoặc nhập vào một biểu mẫu.

Cả hai phương pháp để dịch một số nguyên sang từ tương ứng và để dịch lại một từ thành số nguyên tương ứng đều được yêu cầu.

Quy tắc

Phải có ánh xạ một-một giữa số nguyên và từ và toàn bộ bộ số nguyên 32 bit (hoặc, đặt theo một cách khác, bất kỳ số nguyên nào từ 0 đến 4294967295) phải được ánh xạ. Mặc dù, rõ ràng, không phải tất cả các từ sẽ có ý nghĩa và việc nhập các từ không ánh xạ tới một số nguyên có thể có hành vi không xác định.

Bạn được tự do quyết định chính xác tập hợp các từ "có thể phát âm" nào có ý nghĩa và cách thực hiện ánh xạ, nhưng các từ ít nhất phải tuân theo các quy tắc sau:

  • Chỉ nên sử dụng 26 chữ cái cơ bản (A ... Z) làm ký tự. Dấu, vỏ, vv ... không nên được sử dụng để mở rộng các kết hợp có thể.
  • Tối đa 9 ký tự cho mỗi từ.
  • hai phụ âm (BCDFGHJKLMNPQRSTVWXZ - 20 khả năng) không nên được đặt cạnh nhau (chúng phải được bao quanh bởi các nguyên âm).
  • hai nguyên âm (AEIOUY - 6 khả năng) không nên được đặt cạnh nhau (chúng phải được bao quanh bởi các phụ âm).

Lưu ý: sơ đồ đơn giản nhất mà bạn có tất cả các từ được xây dựng là CVCVCVCVC( Clà phụ âm và Vnguyên âm) cung cấp cho 4147200000 kết hợp và số nguyên 32 bit có 4294967296 giá trị có thể, vì vậy nó không đủ. Bạn cần mở rộng số lượng kết hợp, bằng cách cho phép các từ ngắn hơn hoặc bằng cách cho phép VCVCVCVCVkết hợp, là tốt.

Các quy tắc tiêu chuẩn khác được áp dụng, và các sơ hở tiêu chuẩn bị cấm.

Đầu vào / đầu ra

Đối với mỗi lần gửi, hai đoạn mã phải được cung cấp:

  • Một số lấy một số nguyên làm đối số / đầu vào và trả về / in từ tương ứng
  • Một từ lấy một từ làm đối số / đầu vào và trả về / in số nguyên tương ứng

Ngoài ra, bạn có thể chọn gửi một đoạn mã xử lý cả hai thao tác:

  • Khi được cung cấp một số nguyên làm đầu vào, nó sẽ xuất ra từ tương ứng
  • Khi được cung cấp một chuỗi làm đầu vào, nó xuất ra số nguyên tương ứng

Điều kiện chiến thắng

Đây là một , câu trả lời có ít byte nhất (khi tính tổng cả hai đoạn mã, cho các giải pháp chọn các đoạn mã riêng biệt) sẽ thắng.


Có bất kỳ hạn chế về không gian hoặc thời gian? Chúng ta có phải vừa trong 32GB bộ nhớ không?
John Dvorak

@JanDvorak Chà, chúng tôi sẽ có thể kiểm tra chương trình của bạn trên máy tính "chuẩn". Nhưng thuật toán nên đơn giản, bạn có ý nghĩ gì đòi hỏi một lượng bộ nhớ lớn như vậy?
mờ mất niềm tin vào SE

Tôi chỉ có thể tạo tất cả các từ có chín chữ cái phù hợp với công thức của bạn và sau đó lập chỉ mục vào tập hợp hoặc thực hiện tìm kiếm nhị phân.
John Dvorak

@JanDvorak Tôi phải thừa nhận rằng tôi đã không nghĩ về điều đó. Tôi đã suy nghĩ nhiều hơn về các giải pháp về cơ bản thực hiện chuyển đổi cơ sở 26, với một số điều chỉnh để đáp ứng các ràng buộc nguyên âm / phụ âm. Nhưng bằng cách nào đó tôi nghi ngờ cách "tàn bạo" mà bạn có trong đầu có thể là đánh gôn hiệu quả. Dù sao, nếu tôi phải thực sự làm rõ điều này, giả sử bạn không được phép phân bổ hơn 4GB bộ nhớ.
mờ mất niềm tin vào SE

Bạn có thể yêu cầu người trả lời chạy mã của họ cho một số giá trị được xác định trước (0,1,10,2 ** 32-1 và tương tự), sau đó quay lại và đưa kết quả vào câu trả lời.
John Dvorak

Câu trả lời:


1

JavaScript (ES6), 205 byte

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

Điểm cắt giữa CVCVCVCVC và VCVCVCVCV là 4e9, do đó bắt đầu sai ở 5244160000 (đầu vào số) hoặc zesuwurib(đầu vào chuỗi).


Sáu tháng sau ... Tôi trao cho bạn điểm chấp nhận, vì bạn là người ngắn nhất (và tôi không thể chấp nhận câu trả lời của rturnbull, điều đó không thỏa mãn sự làm rõ mà tôi đã đưa ra trong các bình luận).
mờ mất niềm tin vào SE

2

PHP, 353 byte

Mã hóa + Giải mã

is_numeric($argn)chứa boolean. Đó là sự thật nếu đầu vào là một số nguyên.

$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 Byte (Mã hóa) + 195 Byte (Giải mã) = 385 Byte

Mã hóa

$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 kết hợp có sẵn

Mã hóa phiên bản trực tuyến không có E_NOTICE

Mở rộng

$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

Đầu vào => Đầu ra

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

Nếu bạn luôn cần kết quả 9 Byte, vui lòng thay thế while($a)bằng while(strlen($r)<9)+ 10 Byte

Giải mã

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

Mở rộng

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

Đầu vào => Đầu ra

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

Giải mã phiên bản trực tuyến không có E_NOTICE

Kiểm tra bổ sung

Nếu chúng ta cần kiểm tra xem một chuỗi có hợp lệ không.

Thêm $x.=$b?:0;vào cuối vòng giải mã + 10 byte

Thay thế echo$s;bằng echo!preg_match('#([01])\1$#',$x)?$s:_;+ 32 byte


1

R, 165 byte

Mã hóa và giải mã trong một chức năng.

Hàm này sử dụng phương pháp brute-force để tạo tất cả các giá trị có thể và sau đó chỉ cần trả về chỉ mục khi nó được đưa vào chuỗi đầu vào và trả về chuỗi khi đầu vào số nguyên. Kết quả là, nó rất chậm và sử dụng 16GB + bộ nhớ!

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 giá trị là có thể. Điều này bao gồm tất cả các chuỗi mẫu CVCVCVCV (C), với C cuối cùng là tùy chọn.


@ mbomb007 Gigabyte, xin lỗi vì lỗi đánh máy. Hàm thực hiện cả mã hóa và giải mã tùy thuộc vào việc đối số là một chuỗi hay một số nguyên. Tôi đã cập nhật bài viết để làm rõ điều đó.
rturnbull

Downvoter có thể để lại một bình luận để đề nghị cải thiện? Cảm ơn.
rturnbull

1
Trong các bình luận của câu hỏi, dim làm rõ rằng bạn không thể sử dụng hơn 4gb bộ nhớ ....
Socratic Phoenix
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.