Chuẩn hóa một số điện thoại


32

Lý lịch

Hầu hết mọi người ở đây nên làm quen với một vài hệ thống cơ sở số nguyên: thập phân, nhị phân, thập lục phân, bát phân. Ví dụ: trong hệ thập lục phân, một số abc.de 16 sẽ đại diện cho

a*16^2 + b*16^1 + c*16^0 + d*16^-1 + e*16^-2

Tuy nhiên, người ta cũng có thể sử dụng các cơ sở không nguyên, như các số vô tỷ. Một khi cơ sở này sử dụng tỷ lệ vàng φ = (1 + √5) / 2 ≈ 1.618 ... . Chúng được định nghĩa tương tự với các cơ sở số nguyên. Vì vậy, một số abc.de φ (nơi một để e là số nguyên chữ số) sẽ đại diện

a*φ^2 + b*φ^1 + c*φ^0 + d*φ^-1 + e*φ^-2

Lưu ý rằng về nguyên tắc, bất kỳ chữ số nào cũng có thể âm (mặc dù chúng tôi không quen với điều đó) - chúng tôi sẽ đại diện cho một chữ số âm có chữ số đứng đầu ~. Với mục đích của câu hỏi này, chúng tôi giới hạn bản thân thành các chữ số từ ~9đến 9, vì vậy chúng tôi có thể viết rõ ràng một số dưới dạng một chuỗi (có dấu ngã ở giữa). Vì thế

-2*φ^2 + 9*φ^1 + 0*φ^0 + -4*φ^-1 + 3*φ^-2

sẽ được viết là ~290.~43. Chúng tôi gọi một số như vậy là một số nhị phân .

Một số phinary luôn có thể được biểu diễn ở dạng tiêu chuẩn , có nghĩa là biểu diễn chỉ sử dụng các chữ số 10không chứa 11bất cứ nơi nào và có dấu trừ tùy chọn để chỉ ra rằng toàn bộ số là âm. (Thật thú vị, mỗi số nguyên có một biểu diễn hữu hạn duy nhất ở dạng tiêu chuẩn.)

Các đại diện không ở dạng chuẩn luôn có thể được chuyển đổi thành dạng chuẩn bằng các quan sát sau:

  1. 011 φ = 100 φ (vì φ 2 = φ + 1)
  2. 0200 φ = 1001 φ (vì φ 2 + 1 / φ = 2φ)
  3. 0 ~ 10 φ = ~ 101 φ (vì φ - 1 / φ = 1)

Ngoài ra:

  1. Nếu chữ số có nghĩa nhất là ~1(với phần còn lại của số là dạng chuẩn), số đó là số âm và chúng ta có thể chuyển đổi nó thành dạng chuẩn bằng cách hoán đổi tất cả 1~1, thêm một dấu trừ và áp dụng lại ba quy tắc trên cho đến khi chúng ta có được hình thức tiêu chuẩn.

Dưới đây là một ví dụ về việc chuẩn hóa như vậy (Tôi đang sử dụng khoảng trắng bổ sung cho các chữ số dương, để giữ cho mỗi vị trí chữ số được căn chỉnh): 1~3.2~1φ

      1~3. 2~1φ         Rule:
=     0~2. 3~1φ         (3)
=    ~1~1. 4~1φ         (3)
=  ~1 0 0. 4~1φ         (3)
=  ~1 0 0. 3 0 1φ       (3)
=  ~1 0 1. 1 0 2φ       (2)
=  ~1 1 0. 0 0 2φ       (1)
=  ~1 1 0. 0 1 0 0 1φ   (2)
= - 1~1 0. 0~1 0 0~1φ   (4)
= - 0 0 1. 0~1 0 0~1φ   (3)
= - 0 0 1.~1 0 1 0~1φ   (3)
= - 0 0 0. 0 1 1 0~1φ   (3)
= - 0 0 0. 0 1 1~1 0 1φ (3)
= - 0 0 0. 0 1 0 0 1 1φ (3)
= - 0 0 0. 0 1 0 1 0 0φ (1)

Năng suất .-0.0101φ

Để đọc thêm, Wikipedia có một bài viết rất nhiều thông tin về chủ đề này.

Các thách thức

Do đó, hoặc nói cách khác, viết một chương trình hoặc hàm, được đưa ra một chuỗi đại diện cho một số nhị phân (như được mô tả ở trên), đưa ra dạng chuẩn của nó, mà không có các số 0 đầu hoặc cuối. Đầu vào không nhất thiết phải chứa điểm nhị phân, nhưng sẽ luôn chứa chữ số còn lại của nó (vì vậy không .123). Đầu ra phải luôn bao gồm điểm phinary và ít nhất một chữ số ở bên trái của nó.

Bạn có thể nhận đầu vào thông qua STDIN, ARGV hoặc đối số hàm và trả về kết quả hoặc in ra STDOUT.

Bạn có thể sử dụng một thuật toán khác với quy trình trên miễn là về nguyên tắc chính xác và chính xác cho các đầu vào tùy ý (hợp lệ) - đó là các giới hạn duy nhất có khả năng phá vỡ triển khai của bạn phải là các giới hạn kỹ thuật như kích thước tích hợp loại dữ liệu hoặc RAM có sẵn. Chẳng hạn, việc đánh giá đầu vào là một số dấu phẩy động và sau đó chọn các chữ số một cách tham lam là không được phép, vì người ta có thể tìm thấy các đầu vào mà sự không chính xác của dấu phẩy động sẽ dẫn đến kết quả không chính xác.

Đây là mã golf, câu trả lời ngắn nhất (tính bằng byte) sẽ thắng.

Các trường hợp thử nghiệm

Input       Output

1           1.
9           10010.0101
1.618       10000.0000101
1~3.2~1     -0.0101
0.~1021     0. (or -0.)
105.~2      1010.0101
~31~5.~1    -100000.1001

Bây giờ tôi muốn sử dụng các chữ số âm trong số của tôi! 1 ~ 3 * 6 == 5 ~ 8
Aaron

Câu trả lời:


6

Javascript (ES6) - 446 418 422 420 byte

Giảm thiểu:

F=s=>{D=[];z='000000000';N=t=n=i=e=0;s=(z+s.replace(/^([^.]*)$/,'$1.')+z).replace(/~/g,'-').replace(/-?\d/g,s=>((D[n++]=s/1),0));for(;i<n-3;i=j){if(p=D[j=i+1]){if(!e&&p<0){D=D.map(k=>-k);N=~N;p=-p}e=1}d=D[i];x=D[i+2];m=D[i+3];if(p<0){d--;p++;x++;e=j=0}if(p>1){d++;m++;p-=2;e=j=0}if(!d&&p*x==1){d=p;e=j=p=x=0}D[i]=d;D[i+1]=p;D[i+2]=x;D[i+3]=m}return(N?'-':'')+s.replace(/0/g,()=>D[t++]).replace(/^(0(?!\.))+|0+$/g,'')}

Mở rộng:

F = s => {
    D = [];
    z = '000000000';
    N = t = n = i = e = 0;
    s = (z + s.replace( /^([^.]*)$/, '$1.' ) + z).replace( /~/g, '-' ).
        replace( /-?\d/g, s => ((D[n++]=s/1),0) );

    for( ; i < n-3; i = j ) {
        if( p = D[j = i+1] ) {
            if( !e && p < 0 ) {
                D = D.map( k=>-k );
                N = ~N;
                p = -p;
            }
            e = 1;
        }
        d = D[i];
        x = D[i+2];
        m = D[i+3];

        if( p < 0 ) {
            d--;
            p++;
            x++;
            e = j = 0;
        }
        if( p > 1 ) {
            d++;
            m++;
            p-=2;
            e = j = 0;
        }
        if( !d && p*x == 1 ) {
            d = p;
            e = j = p = x = 0;
        }

        D[i] = d;
        D[i+1] = p;
        D[i+2] = x;
        D[i+3] = m;
    }

    return (N ? '-' : '') + s.replace( /0/g, ()=>D[t++] ).replace( /^(0(?!\.))+|0+$/g, '' );
}

Mã tạo ra một chức năng Fthực hiện chuyển đổi được chỉ định.

Đó là một vấn đề khó khăn với golf. Nhiều trường hợp cạnh leo lên mà ngăn chặn đơn giản hóa mã. Cụ thể, xử lý các tiêu cực là một nỗi đau, cả về phân tích cú pháp và về mặt xử lý logic.

Tôi nên lưu ý rằng mã chỉ xử lý một "phạm vi hợp lý" của đầu vào. Để mở rộng miền của hàm mà không bị ràng buộc, số lượng số không trong zcó thể được tăng lên và liên kết giới hạn của while( c++ < 99 )vòng lặp có thể được tăng lên. Phạm vi hiện được hỗ trợ là quá mức cần thiết cho các trường hợp thử nghiệm được cung cấp.

Đầu ra mẫu

F('1')          1.
F('9')          10010.0101
F('1~3.2~1')    -0.0101
F('0.~1021')    -0.
F('105.~2')     1010.0101
F('~31~5.~1')   -100000.1001

Điều -0.này không đẹp, nhưng câu trả lời vẫn đúng. Tôi có thể sửa nó nếu cần thiết.


@ MartinBüttner: Bạn có thể, nhưng nó sẽ khó khăn. Nó giới hạn số lượng "vượt qua" trên toàn bộ đầu vào và mỗi lần vượt qua bao gồm một số thao tác. Tôi cảm thấy ruột thịt là số lượng đường chuyền cần thiết để bình thường hóa bất kỳ nđầu vào số nào sẽ nằm ở giữann log(n). Trong mọi trường hợp, số lượng đường chuyền có thể được tăng lên theo hệ số 10 cho mỗi ký tự được thêm vào. Số lượng số không trong zhằng số cũng là một vấn đề thú vị. Tôi nghi ngờ rằng 9 là quá mức cho bất kỳ đầu vào có thể.
COTO

@ MartinBüttner: Cảm ơn. Tôi loại bỏ lối thoát trong lớp nhân vật. Đối với $0, Javascript không hỗ trợ nó. Hoặc ít nhất Firefox không có. : P
COTO

Được rồi, tôi nghĩ rằng bạn không bao giờ cần nhiều hơn 7 số 0 đứng đầu làm bộ đệm, nhưng tôi nghĩ các số 0 ở cuối sẽ khó hơn một chút để ước tính. Đối với vòng lặp bên ngoài, tôi không nghĩ bạn thậm chí cần điều đó, nếu bạn chỉ thực hiện vòng lặp while đó (hoặc tích hợp nó vào vòng lặp for bên trong) và chỉ thoát ra khi không tìm thấy thêm thay đổi. Tôi đoán thông số kỹ thuật của tôi có thể rõ ràng hơn một chút về khía cạnh đó nhưng bởi "về nguyên tắc chính xác và chính xác cho các đầu vào tùy ý (hợp lệ)" tôi có nghĩa là giới hạn lý thuyết duy nhất phải là kích thước của các loại dữ liệu tích hợp / RAM của bạn.
Martin Ender

1
@COTO Để tiết kiệm 1 byte, bạn có thể thử di chuyển phần đầu tiên của for( i = e = 0; i < n-3; i = j ) bằng cách for(; i < n-3; i = j )di chuyển các khai báo lên trên cùng, được N = t = n = 0;thay thế bằngN = t = n = i = e = 0;
Ismael Miguel

1
@IsmaelMiguel: jkhông được giữ ở giá trị là i+1. Thông báo trong ba ifkhối, jđược đặt lại thành 0. Do đó tại bất kỳ thời điểm nào sau ifkhối đầu tiên, nó không thể được sử dụng làm proxy cho i+1. Biến itự nó không thể được cập nhật cho đến khi kết thúc vòng lặp (sử dụng câu lệnh thứ ba trongfor ) vì giá trị của nó được sử dụng cho đến hết vòng lặp. Nhưng có nói rằng, có lẽ tôi đang thiếu một cái gì đó. Nếu bạn có thể rút ngắn mã, kiểm tra mã và xác minh rằng nó vẫn hoạt động, vui lòng gửi một bản sao lên pastebin.com và một liên kết tại đây. Tôi sẽ gia hạn tín dụng cho bạn trong câu trả lời. :)
COTO

2

Haskell, 336 byte

z=[0,0]
g[a,b]|a*b<0=g[b,a+b]
g x=x<z
k![a,b,c,d]=[b,a+b,d-c+read k,c]
p('.':s)=1:0:2`drop`p s
p('~':k:s)=['-',k]!p s
p(k:s)=[k]!p s
p[]=1:0:z
[1,0]&y='.':z?y
[a,b]&y=[b,a+b]?y
x@[a,b]?y@[c,d]|x==z,y==z=""|g y='-':x?[-c,-d]|g[c-1,d]='0':x&[d,c+d]|g[c,d-1]='1':x&[d,c+d-1]|0<1=[b-a,a]?[d-c,c]
m[a,b,c,d]=[1,0]?[a*d+b*c-a*c,a*c+b*d]
f=m.p

Đây là thuật toán tham lam, nhưng với cách biểu diễn chính xác [a,b]các số a + ( a , b ∈) để tránh các lỗi dấu phẩy động. g[a,b]kiểm tra xem a + <0. Ví dụ sử dụng:

*Main> f "9"
"10010.0101"
*Main> f "1~3.2~1"
"-0.0101"
*Main> f "0.~1021"
"0."
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.