Làm thế nào trên trái đất, llhuii đã tạo ra Số Ác trong 42 byte Python?


71

Đây là một câu hỏi mẹo để chơi gôn trong Python liên quan đến câu hỏi Evil Numbers trên Anarchy Golf .

Một số là xấu nếu mở rộng nhị phân của nó có số chẵn là 1. Thách thức là in 400 số ác đầu tiên 0,3,5,...,795,797,798, mỗi số một dòng.

Việc đệ trình Python 2 được dẫn dắt bởi llhuii với giải pháp 42 byte. Tốt nhất tiếp theo là 46 byte bởi mitchs, tiếp theo là năm lần gửi 47 byte. Có vẻ như llhuii đã tìm thấy thứ gì đó thực sự kỳ diệu đã lảng tránh nhiều tay golf Python mạnh trong hơn 2 năm. Tiết kiệm 4 hoặc 5 byte là rất lớn cho một sân golf ngắn như vậy.

Bảng điểm Python 2

Tôi vẫn ở mức 47 byte. Tôi hy vọng chúng ta có thể giải câu đố này như một cộng đồng. Nếu chúng tôi nhận được câu trả lời chung, tôi sẽ gửi nó dưới tên của tất cả những người đã đóng góp. Một câu trả lời cho câu hỏi này có thể là một đoạn mã hoặc một ý tưởng mới hoặc một đoạn phân tích. Nếu bạn là llhuii, xin đừng làm hỏng nó cho chúng tôi.

Mặc dù bài nộp không được tiết lộ vì vấn đề này là Vô tận, chúng tôi đã đưa ra một số khách hàng tiềm năng. Bài nộp chiến thắng mất 0,1699 giây để chạy, lâu hơn bất kỳ bài nào khác, cho thấy một phương pháp không hiệu quả. Từ thống kê byte, trong số 42 ký tự, 23 là chữ và số[0-9A-Za-z] và và 19 là ký hiệu ASCII. Điều này có nghĩa là không có khoảng trắng trong giải pháp của llhuii.

Bạn có thể kiểm tra mã của mình trên trang sự cố , chọn Python từ trình đơn thả xuống ngôn ngữ hoặc tải lên .pytệp. Lưu ý rằng:

  • Python 2.7 được sử dụng
  • Mã của bạn phải là một chương trình đầy đủ in
  • Không có đầu vào cho vấn đề này, như
  • Chương trình của bạn chỉ cần in 400 giá trị như đã cho, ngay cả khi nó sẽ phá vỡ các giá trị lớn hơn
  • Chương trình có 2 giây để chạy
  • Các chương trình có thể chấm dứt với lỗi
  • Bạn có thể sử dụng exec; "exec bị từ chối" đề cập đến shell exec

2
Cũng có thể đáng lưu ý rằng chuỗi này là "Chỉ số không trong chuỗi Thue-Morse A010060." (nguồn: oeis )
Conor O'Brien

Câu trả lời:


51

Đây không phải là giải pháp tương tự như llhuii, nhưng nó cũng dài 42 byte.

n=0;exec'print n;n^=(n^n+2)%3/2;n+=2;'*400

Hãy thử trực tuyến!

Cảm ơn @JonathanFrech, chúng tôi hiện có 40 byte.

n=0;exec'print n;n=n+2^(n^n+2)/2%3;'*400

Hãy thử trực tuyến!

Có một byte khác được lưu, với tổng số 39.

n=0;exec'print n;n=n+2^-(n^n+2)%3;'*400

Hãy thử trực tuyến!


1
Vì tò mò, làm sao bạn biết phiên bản 42 byte không giống với llhuii? (Tôi chưa bao giờ tham gia Anarchy Golf)
Luis Mendo

6
@LuisMendo Tab Thống kê liệt kê 23 byte chữ số và 19 ký hiệu ASCII, do đó không có khoảng trắng. Trừ khi llhuii viết print+n, giải pháp của họ phải khác với tôi.
Dennis

À, vậy bạn có thể lấy một số thông tin ngay cả khi bạn không biết mã. Điều đó thật tuyệt. Cảm ơn!
Luis Mendo

Bạn có nghĩ rằng có cơ hội cho một 38? Về lý thuyết, có một số mức độ tự do để có khả năng loại bỏ -dấu hiệu bằng cách thay đổi print~nhoặc print-nsử dụng &hoặc ~, mặc dù tôi không có gì để làm việc. Ngoài ra, n=0;exec"print n;d=n^n+2;n^=d^-d%3;"*400là khá nhưng 40 byte.
xnor

print-ndường như không thể xảy ra vì không có mối quan hệ dễ dàng giữa các bit set n-n. print~nVề mặt lý thuyết có vẻ hứa hẹn hơn, nhưng tôi không thể đạt được dưới 40 byte với phương pháp này.
Dennis

28

Nhận 39 byte

Đây là một lời giải thích về cách tôi có một giải pháp 39 byte, mà Dennis và JonathanFrech cũng tìm thấy riêng. Hay nói đúng hơn, nó giải thích làm thế nào người ta có thể đi đến câu trả lời trong nhận thức muộn màng, theo cách mà nó đẹp hơn nhiều so với con đường thực tế của tôi đến nó, nơi đầy lý luận lầy lội và ngõ cụt.

n=0
exec"print n;n=n+2^-(n+2^n)%3;"*400

Viết cái này ít chơi gôn hơn và có nhiều parens hơn, nó trông giống như:

n=0
for _ in range(400):
  print n
  n=(n+2)^(-((n+2)^n))%3

Chẵn lẻ bit

Chúng tôi bắt đầu với một ý tưởng từ giải pháp 47 byte của tôi để xuất ra tất cả các số của biểu mẫu n=2*k+bnơi kđếm ngược 0,1,...,399b là một bit chẵn lẻ làm cho tổng số 1 chẵn.

Chúng ta hãy viết par(x)cho tính chẵn lẻ của bitx , đó là xor ( ^) tất cả các bit trong x. Đây là 0 nếu có số bit 1 chẵn (số là xấu) và 1 nếu có số lẻ 1 bit. Vì n=2*k+b, chúng ta có par(n) = par(k)^b, vì vậy để đạt được cái ác par(n)==0chúng ta cần b=par(k), tức là bit cuối cùng nlà bit chẵn lẻ của các bit trước.

Những nỗ lực đầu tiên của tôi khi chơi golf là thể hiện par(k), lúc đầu trực tiếp với bin(k).count('1')%2, và sau đó với thao tác bit .

Cập nhật chẵn lẻ

Tuy nhiên, dường như không có một biểu hiện ngắn. Thay vào đó, nó giúp nhận ra rằng có nhiều thông tin hơn để làm việc. Thay vì chỉ tính toán tính chẵn lẻ của số hiện tại,

k  ---->  par(k)

chúng ta có thể cập nhật tính chẵn lẻ bit khi chúng ta tăng klên k+1.

k   ---->  par(k)
      |
      v
k+1 ---->  par(k+1)

Đó là, vì chúng tôi đang đếm k=0,1,2,..., chúng tôi chỉ cần duy trì tính chẵn lẻ bit hiện tại thay vì tính toán từ đầu mỗi lần. Bản cập nhật bit chẵn lẻ par(k+1)^par(k)là chẵn lẻ của số bit lộn trong đi từ kđến k+1, đó là par((k+1)^k).

par(k+1) ^ par(k) = par((k+1)^k)
par(k+1) = par(k) ^ par((k+1)^k)

Hình thức (k+1)^k

Bây giờ chúng ta cần tính toán par((k+1)^k). Có vẻ như chúng ta chẳng đi đến đâu vì tính toán tương đương bit chính xác là vấn đề chúng ta đang cố gắng giải quyết. Nhưng, các số được biểu thị là (k+1)^kcó dạng 1,3,7,15,.., đó là một dưới mức lũy thừa 2, một thực tế thường được sử dụng trong các bản hack bit . Hãy xem tại sao lại như vậy.

Khi chúng ta tăng lên k, hiệu ứng của mang nhị phân là đảo ngược cái cuối cùng 0và tất cả 1sang bên phải của nó, tạo ra một vị trí dẫn đầu mới 0nếu không có. Ví dụ: lấyk=43=0b101011

      **
  101011  (43)
 +     1
  ------
= 101100  (44)

  101011  (43)
 ^101100  (44)
  ------
= 000111  (77)   

Các cột gây ra mang được đánh dấu bằng *. Những cái này có một 1sự thay đổi thành a 0và truyền một bit carry 1, nó tiếp tục truyền sang trái cho đến khi nó chạm 0vào k, nó thay đổi thành 1. Bất kỳ bit nào bên trái không bị ảnh hưởng. Vì vậy, khi k^(k+1)kiểm tra mà cắn vị trí thay đổi kđể k+1, nó tìm thấy vị trí của các đầu mút bên phải 01's bên phải của nó. Nghĩa là, các bit thay đổi tạo thành một hậu tố, do đó, kết quả là 0 được theo sau bởi một hoặc nhiều 1. Không có các số 0 đứng đầu, có các số nhị phân 1, 11, 111, 1111, ...nằm dưới một lũy thừa 2.

Máy tính par((k+1)^k)

Bây giờ chúng tôi hiểu rằng (k+1)^knó bị giới hạn 1,3,7,15,..., chúng ta hãy tìm cách tính tính chẵn lẻ của các số đó. Ở đây, một thực tế hữu ích là 1,2,4,8,16,...modulo thay thế 3giữa 12, kể từ đó 2==-1 mod 3. Vì vậy, lấy 1,3,7,15,31,63...modulo 3đưa ra 1,0,1,0,1,0..., chính xác là tương đương bit của họ. Hoàn hảo!

Vì vậy, chúng tôi có thể thực hiện cập nhật par(k+1) = par(k) ^ par((k+1)^k)như

par(k+1) = par(k) ^ ((k+1)^k)%3

Sử dụng bnhư biến chúng ta lưu trữ chẵn lẻ trong, điều này trông giống như

b^=((k+1)^k)%3

Viết mã

Đặt mã này cùng nhau trong mã, chúng tôi bắt đầu kvà bit chẵn lẻ bcả hai 0, sau đó liên tục in n=2*k+bvà cập nhật b=b^((k+1)^k)%3k=k+1.

46 byte

k=b=0
exec"print 2*k+b;b^=(k+1^k)%3;k+=1;"*400

Hãy thử trực tuyến!

Chúng tôi loại bỏ dấu ngoặc xung quanh k+1trong ((k+1)^k)%3Python được ưu tiên thực hiện việc bổ sung đầu tiên dù sao, lạ vì nó trông.

Cải tiến mã

Chúng ta có thể làm tốt hơn bằng cách làm việc trực tiếp với một biến duy nhất n=2*k+bvà thực hiện các cập nhật trực tiếp trên nó. Làm k+=1tương ứng với n+=2. Và, cập nhật b^=(k+1^k)%3tương ứng với n^=(k+1^k)%3. Ở đây, k=n/2trước khi cập nhật n.

44 byte

n=0
exec"print n;n^=(n/2+1^n/2)%3;n+=2;"*400

Hãy thử trực tuyến!

Chúng ta có thể rút ngắn n/2+1^n/2(hãy nhớ điều này (n/2+1)^n/2) bằng cách viết lại

n/2+1 ^ n/2
(n+2)/2 ^ n/2
(n+2 ^ n)/2    

/2loại bỏ bit cuối cùng, không có vấn đề gì nếu chúng ta làm điều đó trước hoặc sau khi xor-ing. Vì vậy, chúng tôi có n^=(n+2^n)/2%3. Chúng ta có thể lưu một byte khác bằng cách lưu ý rằng modulo 3, /2tương *2đương với -, lưu ý rằng n+2^nthậm chí là phân chia thực sự giảm một nửa mà không cần sàn. Điều này mang lạin^=-(n+2^n)%3

41 byte

n=0
exec"print n;n^=-(n+2^n)%3;n+=2;"*400

Hãy thử trực tuyến!

Cuối cùng, chúng ta có thể kết hợp các hoạt động n^=c;n+=2vào n=(n+2)^c, cmột chút. Điều này hoạt động vì ^cchỉ hoạt động trên bit cuối cùng và +2không quan tâm đến bit cuối cùng, vì vậy các hoạt động đi lại. Một lần nữa, ưu tiên cho phép chúng tôi bỏ qua parens và viết n=n+2^c.

39 byte

n=0
exec"print n;n=n+2^-(n+2^n)%3;"*400

Hãy thử trực tuyến!


13

Điều này mang lại cho giải pháp 47 byte (xnor's) của tôi và suy nghĩ đã đưa tôi đến với nó. Đừng đọc nó nếu bạn muốn tự mình tìm ra điều này.

Một ý tưởng đầu tiên tự nhiên là lặp qua các số từ 0 đến 799, chỉ in những số có số chẵn 1 giây ở dạng nhị phân.

52 byte

for n in range(800):
 if~bin(n).count('1')%2:print n

Hãy thử trực tuyến!

Ở đây, phần ~bổ sung bit để chuyển đổi even<->oddsố đếm và chỉ đưa ra một giá trị trung thực trên các số chẵn.

Chúng tôi có thể cải thiện phương pháp này bằng cách tạo tất cả các giá trị thay vì lọc. Quan sát rằng các giá trị đầu ra là các số từ 0 đến 399, mỗi số có một bit được nối để tạo số 1 bit chẵn.

0 = 2*0 + 0
3 = 2*1 + 1
5 = 2*2 + 1
6 = 2*3 + 0
...

Vì vậy, nsố thứ là một 2*n+btrong hai b=0hoặc b=1. Có bthể tìm thấy bit bằng cách đếm 1các bit trong nvà lấy modulo đếm 2.

49 byte

for n in range(400):print 2*n+bin(n).count('1')%2

Hãy thử trực tuyến!

Chúng ta có thể cắt 2 byte 2*bằng cách lặp đi lặp lại 0,2,4,..., điều này không có khả năng là số lượng 1. Chúng ta có thể làm điều này bằng cách sử dụng một execvòng lặp chạy 400 lần và tăng nthêm 2 vòng mỗi vòng.

47 byte

n=0;exec"print n+bin(n).count('1')%2;n+=2;"*400

Hãy thử trực tuyến!

Và, đó là giải pháp 47 byte của tôi. Tôi nghi ngờ nhất nếu không phải tất cả các giải pháp 47 byte khác đều giống nhau.


1
47 byte của bạn có execđược phép dài không?
Jonathan Frech

1
@JonathanFrech Có, khi trang nói "exec bị từ chối", nó không đề cập đến Python execmà là dòng lệnh exec.
xnor

9

trình 3 Python

Dưới đây là bản đệ trình Python 3 cho Số Ác tại thời điểm viết:

nhập mô tả hình ảnh ở đây

llhuii có lẽ đã chuyển mánh khóe của họ sang Python 3 và đưa ra một giải pháp đó là

  • 3 byte dài hơn giải pháp Python 2 của họ và
  • có 45 - (25 + 18) = 2 byte khoảng trắng.

Chuyển 47B của xnor sang Python 3 theo nghĩa đen, chúng tôi nhận được 50B này:

n=0;exec("print(n+bin(n).count('1')%2);n+=2;"*400)

Tôi đã gửi nó như ppcg(xnor). (Nó thêm dấu ngoặc đơn vào execprint , hiện là các hàm.) Nó có các số liệu thống kê mã khác với các câu trả lời Python 3 khác, tất cả đều có một số khoảng trắng trong chúng. Hấp dẫn!

Có một cách ngắn hơn để viết lại mặc dù ( execcó xu hướng mất lợi thế cạnh tranh trong Python 3):

n=0
while n<800:print(n+bin(n).count('1')%2);n+=2

Đó là 49 byte. Tôi đã gửi nó như ppcg(xnor,alternative). Điều này có hai byte khoảng trắng, giống như câu trả lời của llhui! Điều này khiến tôi tin rằng câu trả lời Python 3 của llhuii trông giống như thế này (dòng mới, sau đó là một whilevòng lặp.) Vì vậy, llhuii có thể được sử dụng exectrong Python 2 và whiletrong Python 3, giống như chúng ta; điều này giải thích sự khác biệt về khoảng trắng.


47B của chúng tôi đã trở thành 49B trong Python 3. Điều thú vị là, bây giờ, 42B của chúng tôi đã không trở thành 44B, nó trở thành 45B! Một cái gì đó về giải pháp của llhuii cần thêm một byte trong Python 3. Điều này có thể có nghĩa là nhiều thứ khác nhau.

  • Điều đầu tiên xuất hiện trong tâm trí là sự phân chia : có thể llhuii sử dụng /trong Python 2, đã trở thành //Python 3. (Nếu chúng được tính bằng twos như chúng ta, thì n/2có thể được sử dụng để dịch nngược về bên phải một chút không?)

  • Một điều khác mà tôi nghĩ đến là các toán tử đơn nguyên sau khi in . Chúng tôi print blahđã trở thành print(blah)(thêm 1 byte), nhưng nếu llhuii đã viết một cái gì đó giống như print~-blahtrong Python 2, thì nó sẽ trở thành print(~-blah)Python 3.

  • Có thể có những ý tưởng khác. Làm ơn cho tôi biết.

Thống kê mã cho tất cả các giải pháp Py3, bao gồm cả của tôi bây giờ:

nhập mô tả hình ảnh ở đây


1
Điều tôi thấy thú vị là giải pháp Python 3 của họ nhanh hơn đáng kể so với giải pháp Python 2 của họ. Hoặc là họ đang sử dụng một số tính năng Python hiệu quả hơn trong Python 3 hoặc đó không phải là một cổng đơn giản (có lẽ họ đã tìm thấy giải pháp Python 3 ngắn hơn cổng trực tiếp).
Jonathan Frech

2
Thời gian chạy trên anagol có sự chênh lệch lớn , tôi nhận xét về OP rằng thời gian chạy của nó ở đây khiến tôi nghĩ rằng thời gian chạy Py2 của chúng chỉ là một cá trích đỏ / ngoại lệ
Lynn

Ngoài ra, tôi giả định XNOR tìm thấy một thủ thuật rất giống nhau và cải thiện trên đó (không thể có nhiều cách để in số ác, phải không ?!) và giải pháp của họ là rất nhiều nhanh chóng!
Lynn

7

Các cách tiếp cận khác

1) Sử dụng công thức cho A001969

Thay vì chuyển đổi thành nhị phân, có thể tận dụng công thức sau (từ OEIS ):

a(1) = 0
for n > 1: a(n) = 3*n-3-a(n/2) if n is even
           a(n) = a((n+1)/2)+n-1 if n is odd

Tôi rất tệ trong việc chơi golf trong Python, vì vậy tôi thậm chí sẽ không thử. Nhưng đây là một nỗ lực nhanh chóng trong JS.

Lưu ý: Tôi không nghĩ rằng đó sẽ là một đệ trình JS hợp lệ vì nó chỉ điền vào một mảng mà không hiển thị nó. Và ngay cả như vậy, nó dài hơn 5 byte so với giải pháp JS tốt nhất hiện tại (là 45 byte). Nhưng dù sao đó không phải là vấn đề ở đây.

for(a=[n=0,3];n<199;)a.push(2*++n+a[n],6*n+3-a[n])

Hy vọng nó có thể cho một số cảm hứng.

Sử dụng một mảng có lẽ không phải là một ý tưởng tốt bởi vì nó cần phải được khởi tạo và cập nhật. Thay vào đó, có thể hiệu quả hơn (sử dụng kích thước mã) để sử dụng hàm đệ quy , điều này sẽ giải thích tại sao giải pháp chiến thắng lại mất nhiều thời gian hơn các giải pháp khác.

2) Xây dựng chuỗi Thue-Morse với sự thay thế

Về lý thuyết, mã này sẽ hoạt động:

n=0;a="1";b="0";exec"t=a;a+=b;b+=t;print(int(b[n]))+n;n+=2;"*400

Hãy thử trực tuyến!(phiên bản có thể chạy được giới hạn trong 20 điều khoản)

Nó tính toán chuỗi Thue-Morse với các thay thế liên tiếp và tìm kiếm vị trí của 1 (Số Ác) trong cùng một vòng lặp.

Nhưng:

  • Nó quá dài trong hình thức hiện tại của nó
  • Nó nhanh chóng dẫn đến tràn bộ nhớ

3) Xây dựng chuỗi Thue-Morse với các thao tác bitwise

Bắt đầu từ Định nghĩa trực tiếp của Wikipedia về trình tự Thue-Morse , tôi đã đến với thuật toán này (chuyển về JS ... xin lỗi):

for(e=n=0;n<799;)(e^=!(((x=n++^n)^x/2)&170))||console.log(n)

trong đó chúng tôi theo dõi sự xấu xa hiện tại của chuỗi trong e và sử dụng 170 như một bitmask của các bit lẻ trong một byte.


Tôi thích ý tưởng về một hàm đệ quy, nhưng Python rất tệ ở chỗ cho bản soạn f=lambda n:_ for n in range(400):print f(n)sẵn : đã mất 43 byte. Có thể có một cách để mô phỏng đệ quy bằng cách xây dựng một mảng tham chiếu chính nó hoặc một mảng thêm các phần tử trong tương lai vào cuối.
xnor

2
Ngoài ra, giải pháp llhuii của không có khoảng trống trong nó, vì vậy ông không sử dụng def, for, while, lambda(với một tham số tối thiểu), vv
Stephen

@Stephen Một cái gì đó như while~0:print~1không yêu cầu bất kỳ không gian.
Jonathan Frech

Trong phương thức số 3, ((x=n++^n)^x/2)có vẻ hơi dài dòng chỉ để tìm bit đặt thấp nhất. Toàn bộ mớ hỗn độn có thể được thay thế bởi ++n&-n. Hãy thử trực tuyến!
Primo

@primo Tôi không biết tôi đang nghĩ gì ở đây và làm thế nào tôi đến với công thức rườm rà này. ¯ \ _ (ツ) _ / ¯
Arnauld

5

Cách tiếp cận quầy lồng

Tôi có một ý tưởng cho một cách tiếp cận khác, nhưng tôi không đủ kinh nghiệm trong việc chơi golf trăn, vì vậy tôi sẽ để nó ở đây để các bạn xem xét như một điểm khởi đầu khả dĩ khác cho việc chơi golf.

Ý tưởng vô căn cứ:

n=0
i=1
for _ in"01":
 i^=1
 for _ in"01":
  i^=1
  for _ in"01":
   i^=1
   for _ in"01":
    i^=1
    for _ in"01":
     i^=1
     for _ in"01":
      i^=1
      for _ in"01":
       i^=1
       for _ in"01":
        i^=1
        for _ in"01":
          i^=1
          if n<800:print i+n
          n+=2

Hãy thử trực tuyến!

Chín cấp độ sâu làm tổ, tất cả các vòng lặp đều giống nhau, vì vậy trong tâm trí của tôi chúng nên được xây dựng theo exec"something"*9+"deepest stuff". Trong thực tế tôi không biết liệu có thể làm một cái gì đó như thế này với một chu kỳ không.

Những điều cần xem xét để chơi golf:

  • có thể có một số khả năng khác để quay vòng hai lần ngoài vòng lặp for (Tôi đã thử một cách tiếp cận giống như quine với chuỗi được thực thi được truyền cho chính nó như là một đối số định dạng hai lần, nhưng đầu tôi đã nổ tung).

  • cũng có thể có một giải pháp thay thế tốt hơn if n<800:, cần thiết ở đây vì nếu không, chúng tôi sẽ tiếp tục in những con số xấu lên tới 2 ^ 10



Có thể thử hiểu các danh sách lồng nhau thay vì lồng cho các vòng lặp?
Sparr

@Sparr Vấn đề sau đó là thực sự in các số. Trong Python 2, printlà một câu lệnh, không phải là một hàm và do đó không thể xuất hiện bên trong một sự hiểu biết.
Jonathan Frech

có lẽprint '\n'.join([[[[[[[[[foo]foo]foo]foo]foo]foo]foo]foo]foo])
Sparr

@Sparr Sau đó, vấn đề nằm ở việc làm phẳng danh sách; str.joinchỉ hoạt động trên danh sách chứa chuỗi và ký tự danh sách phụ không được in. Định dạng một mình sẽ mất một lượng đáng kể byte.
Jonathan Frech

5

Ý tưởng: chẵn lẻ bit ngắn hơn

Phải mất nhiều ký tự để làm bin(n).count('1')%2tính toán tính chẵn lẻ của bit-Count. Có thể một cách số học ngắn hơn, đặc biệt là với độ dài bit giới hạn.

Một cách có cùng độ dài dễ thương là int(bin(n)[2:],3)%2, diễn giải giá trị nhị phân là cơ sở 3(hoặc bất kỳ cơ sở lẻ nào). Thật không may, 4 trong số các byte được dành để loại bỏ 0btiền tố. Nó cũng hoạt động để làm int(bin(n)[2:])%9%2.

Một ý tưởng khác đến từ việc kết hợp các bit bằng xor. Nếu ncó biểu diễn nhị phân abcdefghi, thì

n/16 = abcde
n%16 =  fghi

r = n/16 ^ n%16 has binary representation (a)(b^f)(c^g)(d^h)(e^i)

Vì vậy, r=n/16^n%16là xấu xa và chỉ khi nlà xấu xa. Sau đó chúng tôi có thể lặp lại điều đó như s=r/4^r%4một giá trị strong 0,1,2,3, trong đó 12không phải là ác, checkable với 0<s<3.

52 byte

n=0;exec"r=n/16^n%16;print(0<r/4^r%4<3)+n;n+=2;"*400

Hãy thử trực tuyến!

Điều này hóa ra một thỏa thuận tốt lâu hơn. Có nhiều nút để chuyển qua cách chia số, cách kiểm tra số cuối cùng (có thể là bảng tra cứu dựa trên bit). Tôi nghi ngờ những điều này chỉ có thể đi rất xa mặc dù.


nó sẽ là một khả năng để sử dụng to_byteschức năng của số nguyên? Tôi nghi ngờ điều đó nhưng có gì đó để xem xét :)
HyperNeutrino

@HyperNeutrino Tôi nghĩ đó chỉ là Python 3?
xnor

yup my bad: / rip
HyperNeutrino

9
Đơn giản chỉ cần sử dụng 0b: int(bin(n),13)%2! : D
Noodle9

3
Phát triển! Thủ thuật của Noodle9 cung cấp giải pháp 44 byte:n=0;exec"print~int(bin(n),13)%2+n;n+=2;"*400
Lynn

4

Bằng cách xây dựng, n+n^nluôn luôn là xấu, nhưng các kỹ năng Python kém của tôi chỉ có thể đưa ra giải pháp 61 byte:

for n in sorted(map(lambda n:n+n^n,range(512)))[:400]:print n

Cảm ơn @Peilonrayz vì đã lưu 5 byte và @ Mr.Xcoder để lưu 1 byte:

for n in sorted(n^n*2for n in range(512))[:400]:print n

55 byte : for n in sorted(n^n*2for n in range(512))[:400]:print n. n+n^ngiống nhưn^n*2
Ông Xcoder

3

Ý tưởng: A006068 (Số a (n) được mã hóa thành màu xám)

Ý tưởng của Neil về việc sắp xếp tất cả những điều 2n XOR nkhiến tôi tò mò, vì vậy tôi đã cố gắng tìm các chỉ số đằng sau loại này. Tôi đã viết mã này và nó tiết lộ rằng chúng ta có thể viết một cái gì đó như thế này:

for n in range(400):x=a(n);print 2*x^x

Nơi a(n)A006068 (n) là. Hãy thử trực tuyến!

Tuy nhiên, điều này giả định rằng chúng ta có một số cách ngắn để tính A006068. Đây đã là 38 byte, giả sử chúng ta có thể tính toán nó trong 4 byte ( a(n)phần). Việc triển khai thực sự (trong tiêu đề TIO) còn lâu hơn thế. Tôi không hy vọng nhiều cho điều này.


3

Ý tưởng: Giảm hơn XOR

Nếu bạn XOR tất cả các bit của nnhau, nó sẽ 0dành cho ác và 1không ác. Bạn có thể làm điều này với một hàm đệ quy (có thể mất nhiều thời gian hơn?), Như vậy:

f=lambda n:f(n/2^n&1)if n>1else-~-n

Điều này trả về 1 cho cái ác.

Đó là 35 byte và kiểm tra xem một số có xấu hay không. Thật không may, filterđã là 6 byte nên đây không phải là giải pháp tối ưu nguyên văn nhưng ý tưởng này có thể được đánh gôn.


Tôi nghĩ bạn có thể làm f=lambda n:n>1and f(n/2^n&1)or-~-ncho -1 byte.
Erik the Outgolfer

@EriktheOutgolfer Tôi đã thử nhưng điều đó gây ra lỗi khi f(n/2^n&1)trả về 0 ...
HyperNeutrino

2

Phương pháp thay thế: {1 -> {1, -1}, -1 -> {-1, 1}}

Bạn cũng có thể thực hiện thay thế này 10 lần {1 -> {1, -1}, -1 -> {-1, 1}}, sau đó làm phẳng và kiểm tra vị trí của 1

đây là mã toán học

(F = Flatten)@
Position[F@Nest[#/.{1->{1,-1},-1->{-1,1}}&,1,10],1][[;; 400]] - 1

Làm thế nào bạn sẽ làm điều này trong python?
Aneesh Durg

2
@AneeshDurg bạn có thấy điều gì thú vị trong giải pháp này không? nghĩ ra khỏi hộp và bạn có thể tìm thấy ý nghĩa của cuộc sống AKA 42
J42161217
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.