Xuất nguồn, mỗi lần một bit


18

Viết chương trình hoặc hàm không trống mà khi được gọi xuất ra một giá trị duy nhất là 1 hoặc 0 và khi được gọi nhiều lần, các số đầu ra tạo ra biểu diễn nhị phân của mã nguồn chương trình của bạn (trong cùng một trang mã mà mã của bạn được biên dịch / diễn giải).

Ví dụ: nếu mã nguồn của bạn là abc(trong ASCII), các đầu ra sẽ là:

1st call:  0           // ASCII letter 'a'
2nd call:  1
3rd call:  1
4th call:  0
5th call:  0
6th call:  0
7th call:  0
8th call:  1

9th call:  0           // ASCII letter 'b'
10th call: 1
11th call: 1
12th call: 0
13th call: 0
14th call: 0
15th call: 1
16th call: 0

17th call: 0           // ASCII letter 'c'
18th call: 1
19th call: 1
20th call: 0
21st call: 0
22nd call: 0
23rd call: 1
24th call: 1

After the 24th call, the behaviour is undefined.

Biểu diễn nhị phân của nguồn phải chứa ít nhất một 0 bit và 1 bit.

Thay vì 1 và 0, bạn có thể xuất bất kỳ hai giá trị riêng biệt, nhất quán nào (như truefalse).

Các chương trình tự sửa đổi tạo ra biểu diễn nhị phân của nguồn ban đầu được cho phép, miễn là chúng không đọc mã nguồn để tìm hiểu những gì sẽ in tiếp theo.

Đây là , vì vậy câu trả lời ngắn nhất bằng byte sẽ thắng.

Câu trả lời:


8

Funky , 47 41 37 byte

Trả về một số đại diện cho một chút.

f=_=>1&("%b"%("f="+f)[i//8])>>7-i++%8

Điều này sử dụng định dạng quine của f=_=>"f="+f. Phải mất nhân vật ở vị trí ⌊i / 8⌋ , sau đó, nhận được chút bằng cách lấy pairity của n >> 7-i%8nơi nlà giá trị ascii của ký tự hiện.

Đây là một hàm lặp tăng dần itheo mỗi cuộc gọi, một khi hết mã nguồn, nó sẽ viết mã nmãi mãi.

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


Đây có phải là một polyglot với JavaScript?
Stan Strum

9

Bash , 105 byte

trap -- 'trap|xxd -b -c1|cut -d\  -f2|tr -d \\n|cut -c`x=\`cat f||echo 1\`;echo $((x+1))>f;echo $x`' EXIT

LƯU Ý : Đảm bảo rằng bạn không có tệp quan trọng được gọi ftrong thư mục bạn đang kiểm tra tệp này.


Nếu bạn muốn kiểm tra điều này, bạn có thể sử dụng lệnh sau:

for i in $(seq 848); do bash path/to/script.sh 2> /dev/null; done | tr -d \\n

Mà nên cho cùng một đầu ra xxd -c1 -b path/to/script.sh|cut -d\ -f2|tr -d \\n.

Giải trình

Đây là sử dụng trapmẹo - gọi trapbên trong traphành động chỉ đơn giản là in dòng đó. Tiếp theo, đầu ra được xxdchuyển sang bộ chuyển đổi thành nhị phân (không may xxd -bpkhông hoạt động - do đó, cách giải quyết với cut& tr):

xxd -c1 -b $0|cut -d\  -f2|tr -d \\n

Từ đó chúng ta chỉ quan tâm đến một bit (giả sử N) mà chúng ta có thể chọn cut -cN.

Để tìm hiểu những gì Nchúng tôi đang sử dụng (hãy nhớ rằng đó là phần cần được tăng lên sau mỗi cuộc gọi), chỉ cần thử đặt thành xnội dung của tệp fvà nếu nó không tồn tại, hãy đặt nó thành 1:

x=`cat f||echo 1`

Điều cuối cùng cần làm là cập nhật tệp f- ghi x+1vào tệp:

echo $((x+1))>f

7

TI-Basic (sê-ri TI-83), 592 357 309 byte

"123456789ABCDEF02A3132333435363738394142434445463004AA003FB958833404593FB9588338045A3F3230363FDA582B383F303FCE5A405A6B3232333F5A70BB0FAA002BBB0CAA002B5A2B313FB932BA32F01058713459713511BB0FAA002BBB0CAA002B597031377132722B31→Str1
iPart(X/4→Y
iPart(X/8→Z
206
IS>(X,8
0
If Z and Z<223
Z+inString(Str1,sub(Str1,Z,1
iPart(2fPart(2^(X-4Y-5)inString(Str1,sub(Str1,Y+17-2Ans,1

Bảng này là một tài liệu tham khảo có thể cho biểu diễn nhị phân của mã nguồn của máy tính, mặc dù cuối cùng tôi chỉ sử dụng trình gỡ lỗi của Virtual TI.

Để so sánh và / hoặc lợi ích lịch sử: các câu hỏi đầu tiên được viết bằng TI-Basic .

Làm thế nào nó hoạt động

Str1lưu trữ mã nguồn (bây giờ là thập lục phân vinh quang, tiết kiệm rất nhiều không gian so với phiên bản nhị phân trước đó), loại bỏ các bit nơi nội dung của Str1chính nó sẽ được trình bày.

Chúng tôi giả định rằng chương trình bắt đầu ra trên một máy tính có bộ nhớ vừa được giải tỏa, vì vậy X0. Mỗi lần qua chương trình, chúng tôi tăng dần X.

Thông thường, chúng tôi chỉ tìm ra nửa byte mà chúng tôi đang cố gắng trích xuất một chút từ, đọc nó ra Str1, chuyển đổi từ thập lục phân sang nhị phân và in nó. Nếu chúng ta đang ở trên một phần của mã nguồn đó là lưu trữ Str1(đó là hai phần ba tổng chiều dài của chương trình), sau đó chúng tôi đầu tiên chuyển sang các phần tương ứng của chuỗi lưu trữ 31, 32và vân vân.


4

Java 8, 249 241 237 234 148 byte

int i;v->{String s="int i;v->{String s=%c%s%1$c;return s.format(s,34,s).charAt(-i/8)>>(--i&7)&1;}";return s.format(s,34,s).charAt(-i/8)>>(--i&7)&1;}

Xin lỗi trước những lời giải thích dài. :)

  • Số lượng 89 byte được lưu nhờ vào @Nevay .

Hãy thử nó ở đây.

Giải trình:

int i;                     // Index-integer on class-level
v->{                       // Method with empty unused parameter and integer return-type
  String s="int i;v->{String s=%c%s%1$c;return s.format(s,34,s).charAt(-i/8)>>(--i&7)&1;}";
                           //  String containing the unformatted source code
  return s.format(s,34,s)  //    Quine to get the source code,
      .charAt(-i/8)        //     and get the character at index `-i/8`
     >>                    //    And bitwise right-shift it with:
       (--i&7)             //     `i-1` bitwise-AND 7
                           //     by first decreasing `i` by 1 with `--i`
      &1;                  //   Then bitwise-AND everything above with 1
}                          // End of method

Giải thích thêm:

-part:

  • String s chứa mã nguồn chưa được định dạng
  • %s được sử dụng để đặt Chuỗi này vào chính nó với s.format(...)
  • %c, %1$c34được sử dụng để định dạng dấu nháy kép ( ")
  • s.format(s,34,s) đặt tất cả lại với nhau

Hãy thử ở đây với một số phần được gỡ bỏ / sửa đổi để xác minh các đầu ra quine mà mã nguồn của chính nó.

-part:


Câu trả lời cũ 233 byte :

int i;v->{String s="int i;v->{String s=%c%s%1$c;return Long.toString((s.format(s,34,s).charAt(i/8)&255)+256,2).substring(1).charAt(i++%%8);}";return Long.toString((s.format(s,34,s).charAt(i/8)&255)+256,2).substring(1).charAt(i++%8);}

Hãy thử nó ở đây.

Giải trình:

int i;                           // Index-integer on class-level
v->{                             // Method with empty unused parameter and char return-type
  String s="int i;v->{String s=%c%s%1$c;return Long.toString((s.format(s,34,s).charAt(i/8)&255)+256,2).substring(1).charAt(i++%%8);}";
                                 //  String containing the unformatted source code
  return Long.toString(
          (s.format(s,32,s)      //  Quine-formatting
          .charAt(i/8)           //  Take the current character
           &255)+256,2).substring(1)
                                 //  Convert it to an 8-bit binary-String 
         .charAt(i++%8);         //  And return the bit at index `i` modulo-8
                                 //  and increase index `i` by 1 afterwards with `i++`
}                                // End of method

Giải thích thêm:

-part:

Giải thích tương tự như trên, với việc bổ sung:

  • %%là dạng thoát của dấu hiệu modulo ( %)

Hãy thử ở đây với một số phần được gỡ bỏ / sửa đổi để xác minh các đầu ra quine mà mã nguồn của chính nó.

-part:

  • i/8sẽ tự động cắt ngắn khi chia số nguyên, vì vậy khi i0-7, nó sẽ trở thành 0; nếu ilà 8-15, nó sẽ trở thành 1; Vân vân.
  • Vì vậy, s.charAt(i/8)lấy ký tự hiện tại của mã nguồn, tám lần sau nhau. Hãy thử nó ở đây với một phiên bản sửa đổi.
  • 2550xFFhoặc 11111111(giá trị tối đa cho một byte không dấu)
  • 2560x100hoặc 100000000.
  • Việc phát &sóng ký tự ASCII thành một số nguyên. Tại thời điểm đó, nó là bất cứ nơi nào giữa 0255( 00000000đến 11111111).
  • Long.toString(...,2) chuyển đổi nó thành biểu diễn chuỗi nhị phân 9 bit
  • +256.substring(1)sẽ đảm bảo có các số 0 đứng đầu và sẽ chuyển đổi 9 bit thành 8 bit.

Hãy thử ở đây với một số phần bị xóa / sửa đổi để xác minh toàn bộ byte.


1
149 byte:int i;v->{String s="int i;v->{String s=%c%s%1$c;return 1&s.format(s,34,s).charAt(-i/8)>>(--i&7);}";return 1&s.format(s,34,s).charAt(-i/8)>>(--i&7);}
Nevay

@Nevay Đã lưu 88 byte. Cảm ơn! Và vì nó thực sự là một cách tiếp cận khác so với ban đầu, tôi đã giữ câu trả lời cũ và thêm câu mới. (Nếu bạn muốn tôi sẽ xóa nó một lần nữa và bạn có thể tự đăng nó, nhưng bạn đã nói với tôi trước đây bạn thích chơi gôn hơn - chủ yếu là mã XD của tôi thay vì đăng câu trả lời của riêng bạn, phải không?)
Kevin Cruijssen

2

Javascript ES6, 73 58 52 byte

o=_=>`o=${o}`.charCodeAt((o.n=1+o.n|0)/8)>>(7-o.n%8)&1

Giải trình

Phân tích mã:

  • o=_=>: xác định hàm.
  • `o=${o}`: xây dựng một chuỗi; ođược chuyển đổi thành một chuỗi, trong trường hợp này là mã nguồn của hàm.
  • .charCodeAt(: lấy một ký tự trong chuỗi làm mã ký tự ASCII của nó.
  • (o.n=1+o.n|0)/8: chọn một ký tự. Đây cũng là nơi bộ đếm được tăng lên.
  • )>>(7-o.n%8): dịch chuyển mã ký tự kết quả sao cho bit mong muốn ở đúng vị trí.
  • &1: đặt tất cả các bit khác thành 0.

Bạn có thể rút ngắn điều này với lambda thànho=_=>(o+'').charCodeAt(('n'in top?++n:n=0)/8|0)>>(7-n%8)&1
ATaco

Điều này được tính là xác định một chức năng.
ATaco

1
Hãy thửo=_=>('o='+o).charCodeAt(('n'in top?++n:n=0)/8|0)>>(7-n%8)&1
ATaco

Thay vì 'n'in top?++n:n=0bạn có thể sử dụng ++n||(n=0)hoặc ++n?n:n=0hoặc n=++n||0hoặc n=1+n||0mà tất cả sử dụng các falsiness của NaNđược sản xuất bằng cách tăngundefined
Bergi

1
o=_=>('o='+o).charCodeAt((o.n=1+o.n|0)/8)>>(~o.n&7)&1
tsh

2

q / kdb + , 45 byte

Giải pháp:

a:-1;f:{((,/)0b vs'4h$"a:-1;f:",($).z.s)a+:1}

Thí dụ:

q)f[] / call function f with no parameters
0b   
q)f[]
1b   
q)f[]
1b   
q)f[]
0b   
q)f[]
0b   
q)f[]
0b   
q)f[]
0b   
q)f[]
1b   
q)f[]  
q)"c"$0b sv 01100001b / join back to a byte and cast to a character
"a"

Giải trình:

Tôi nghĩ rằng tôi hiểu ngắn gọn.

Đầu tiên thiết lập một biến toàn cục avới giá trị bắt đầu là -1. Hàm fxây dựng biểu diễn nhị phân của biểu diễn chuỗi của hàm (mọi thứ bao gồm {}) được thêm vào trước a:-1;f:rác và lập chỉ mục vào danh sách nhị phân này tại chỉ mục a (được tăng lên mỗi cuộc gọi).

a:-1;f:{(raze 0b vs'4h$"a:-1;f:",string .z.s)a+:1} / ungolfed solution
a:-1;                                              / stick -1 in variable a
     f:{                                         } / define function f
                                             a+:1  / increment a by 1 (:: is required as a is a global variable), indexes into the left
        (                                   )      / do all this together
                                 string .z.s       / z.s is the function, string converts it to a string
                       "a:-1;f:",                  / prepend "a:-1;f:" to the start
                    4h$                            / cast to bytes
              0b vs'                               / convert each byte to binary
         raze                                      / flatten binary into long list

2

Python 2 , 164 byte

lambda s='lambda s=%r,i=[]:i.append(1)or"{:08b}".format(ord((s%%s)[~-len(i)/8]))[~-len(i)%%8]',i=[]:i.append(1)or"{:08b}".format(ord((s%s)[~-len(i)/8]))[~-len(i)%8]

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

Giải trình

Hãy bắt đầu với một tiêu chuẩn Python 2 chuẩn.

s = '...'; print s % s

Được rồi, tốt, điều này đầu ra nó chỉ như thế. Chúng ta cần nhị phân!

s = '...'; print "\n".join("\n".join("{:08b}".format(ord(i))) for i in s % s)

Phải, điều đó chỉ chuyển đổi mọi thứ thành nhị phân. Nhưng tiêu đề nói "một chút tại một thời điểm". Chúng tôi cần một cái gì đó để tồn tại qua nhiều lần chạy. Tôi biết, hãy làm cho nó một chức năng!

lambda s = '...': "\n".join("\n".join("{:08b}".format(ord(i))) for i in s % s)

Đợi đã, điều đó không có ích ... Hmm, làm thế nào chúng ta có thể theo dõi chỉ số của bit cần thiết để được đầu ra? Ooh, ooh, chúng ta hãy có một số nguyên để theo dõi.

lambda s = '...', i = 0: "{:08b}".format(ord((s % s)[i / 8]))[i % 8]

Ừm ... luôn luôn xuất ra bit đầu tiên. Oh, chúng ta cần phải tăng theo dõi! Ôi trời, Python không cho phép số nguyên làm đối số mặc định được sửa đổi. Và các bài tập không phải là biểu thức trong Python, vì vậy bạn không thể làm điều đó trong lambda. Welp, điều này là không thể trong Python, trường hợp đóng cửa.

... Chà, không hẳn. Python không cho phép danh sách làm đối số mặc định được sửa đổi. (Và nó cắn các lập trình viên Python mọi lúc.) Hãy sử dụng độ dài của nó!

lambda s = '...', i = []: "{:08b}".format(ord((s % s)[len(i) / 8]))[len(i) % 8]

Điều đó vẫn không sửa đổi trình theo dõi mặc dù ... Chúng ta có thể thêm một cái gì đó vào nó để tăng chiều dài của nó ... Nhưng làm thế nào? Ah, tốt, chúng tôi đã có list.append. lst.append(1)tương đương với lst += [1]. Tuyệt quá!

lambda s = '...', i = []: i.append(1) and "{:08b}".format(ord((s % s)[len(i) / 8]))[len(i) % 8]

Rất tiếc, điều này bỏ qua bit đầu tiên vì độ dài của trình theo dõi là 1 trước khi bit được xuất ra. Chúng ta cần giảm độ dài nơi nó được sử dụng.

lambda s = '...', i = []: i.append(1) and "{:08b}".format(ord((s % s)[(len(i) - 1) / 8]))[(len(i) - 1) % 8]

Đây rồi, thưa các bạn! Chơi gôn và bạn đã có giải pháp của tôi!


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.