Вывод источника, один бит за раз


18

Напишите непустую программу или функцию, которая при вызове выдает одно значение, 1 или 0, а при вызове несколько раз выходные числа дают двоичное представление исходного кода вашей программы (в той же кодовой странице, из которой компилируется ваш код). / интерпретированы).

Например, если ваш исходный код был abc(в ASCII), выходные данные будут:

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.

Двоичное представление источника должно содержать как минимум один бит 0 и один бит 1.

Вместо 1 и 0 вы можете вывести любые два различных согласованных значения (например, trueи false).

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

Это , поэтому выигрывает самый короткий ответ в байтах.

Ответы:


8

Фанки , 47 41 37 байт

Возвращает число, представляющее бит.

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

Это использует формат Quine f=_=>"f="+f. Он принимает символ в позиции ⌊i / 8⌋ , затем получает бит, принимая пару, n >> 7-i%8где nесть значение ascii текущего символа.

Это итеративная функция, которая увеличивается iс каждым вызовом, как только она выходит из исходного кода, она будет писать код nнавсегда.

Попробуйте онлайн!


Это полиглот с JavaScript?
Стэн Струм

9

удар , 105 байт

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

НОТА . Убедитесь, что fв каталоге, который вы тестируете, нет важного файла, который вызывается.


Если вы хотите проверить это, вы можете использовать следующую команду:

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

Который должен дать тот же результат xxd -c1 -b path/to/script.sh|cut -d\ -f2|tr -d \\n.

объяснение

Это использует trapхитрость - вызов trapвнутри trapдействия просто печатает эту строку. Затем этот вывод передается по конвейеру, xxdкоторый преобразует его в двоичный файл (к сожалению xxd -bp, не работает - таким образом, обходится обход с cut& tr):

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

Из этого нас интересует только один бит (скажем N), который мы можем выбрать cut -cN.

Чтобы выяснить, что Nмы используем (помните, что это та часть, которую нужно увеличивать после каждого вызова), просто попробуйте установить xсодержимое файла fи, если он не существует, установите его равным 1:

x=`cat f||echo 1`

Последнее, что нужно сделать, это обновить файл f- запись x+1в него:

echo $((x+1))>f

7

TI-Basic (серия TI-83), 592 357 309 байт

"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

Эта таблица является возможной ссылкой на двоичное представление калькулятора исходного кода, хотя в конечном итоге я просто использовал отладчик Virtual TI.

Для сравнения и / или исторического интереса: первые цитаты, написанные на TI-Basic .

Как это устроено

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

Мы предполагаем , что программа начинается на калькуляторе, память которого только что был очищен, так Xэто 0. Каждый раз через программу мы увеличиваемX .

Обычно мы просто вычисляем половину байта, из которого мы пытаемся извлечь немного, читаем его Str1, преобразуем из шестнадцатеричного в двоичный и печатаем его. Если мы на части исходного кода , который хранящей Str1(что составляет две трети от общей длины программы), то первый шаг к соответствующей части строки хранения 31, 32и так далее.


4

Java 8, 249 241 237 234 148 байт

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

Заранее извините за длинные объяснения. :)

  • Колоссальные 89 байтов сохранены благодаря @Nevay .

Попробуй это здесь.

Объяснение:

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

Дополнительное объяснение:

-часть:

  • String s содержит неформатированный исходный код
  • %s используется, чтобы поместить эту строку в себя с s.format(...)
  • %c, %1$cИ 34используются для форматирования двойных кавычек (" )
  • s.format(s,34,s) складывает все вместе

Попробуйте это здесь с некоторыми частями, удаленными / измененными, чтобы проверить вывод quine его собственного исходного кода.

-часть:


Старый 233 байта ответа:

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);}

Попробуй это здесь.

Объяснение:

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

Дополнительное объяснение:

-часть:

То же объяснение, что и выше, с добавлением:

  • %%является экранированной формой по модулю ( %)

Попробуйте это здесь с некоторыми частями, удаленными / измененными, чтобы проверить вывод quine его собственного исходного кода.

-часть:

  • i/8автоматически усекается при целочисленном делении, поэтому, когда i0-7, оно станет 0; если iбудет 8-15, то станет 1; и т.п.
  • Таким образом, s.charAt(i/8)принимает текущий символ исходного кода, восемь раз друг за другом. Попробуйте здесь с модифицированной версией.
  • 255is 0xFFили 11111111(максимальное значение для байта без знака)
  • 256это 0x100или 100000000.
  • &Сбросы в ASCII-символ в целое число. На этом этапе, это где -то между 0и 255( 00000000в11111111 ).
  • Long.toString(...,2) преобразует его в 9-битное двоичное строковое представление
  • +256и .substring(1)обеспечит наличие начальных нулей, и преобразует 9-разрядный в 8-разрядный.

Попробуйте здесь с некоторыми частями удалены / изменены, чтобы проверить все байты.


1
149 байтов: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 Сохранено 88 байтов. Благодарность! И поскольку на самом деле это немного другой подход, чем у меня изначально, я сохранил старый ответ и добавил новый. (Если вы хотите, я удалю его снова, и вы можете опубликовать его самостоятельно, но в прошлом вы говорили мне, что предпочитаете играть в чужие игры - в основном мой XD-код, а не публиковать свой собственный ответ, верно?)
Кевин Круйссен,

2

Javascript ES6, 73 58 52 байта

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

объяснение

Разбивка кода:

  • o=_=>: определить функцию.
  • `o=${o}`: построить строку; oпреобразуется в строку, которая в данном случае является исходным кодом функции.
  • .charCodeAt(: получить символ в строке как его код символа ASCII.
  • (o.n=1+o.n|0)/8: выберите персонажа. Это также, где счетчик увеличивается.
  • )>>(7-o.n%8): сдвиньте полученный символьный код так, чтобы нужный бит находился в правильном положении.
  • &1: установите все остальные биты в 0.

Вы можете сократить это с o=_=>(o+'').charCodeAt(('n'in top?++n:n=0)/8|0)>>(7-n%8)&1
лямбдой

Это считается как определение функции.
ATaco

1
Попробуйтеo=_=>('o='+o).charCodeAt(('n'in top?++n:n=0)/8|0)>>(7-n%8)&1
ATaco

Вместо 'n'in top?++n:n=0вы можете использовать ++n||(n=0)или ++n?n:n=0или n=++n||0илиn=1+n||0 все, которые используют ложь, NaNкоторая производится путем увеличенияundefined
Берги

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

2

q / kdb + , 45 байт

Решение:

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

Пример:

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"

Объяснение:

Я думаю, что понял краткое.

Сначала настройте глобальную переменную aс начальным значением -1. Функция fсоздает двоичное представление строкового представления функции (все, включая{} ), с добавлением a:-1;f:мусора, и индексирует в этот двоичный список по индексу a (который увеличивается с каждым вызовом).

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 байта

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]

Попробуйте онлайн!

объяснение

Давайте начнем со стандартного Quine Python 2.

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

Хорошо, хорошо, это выводит это просто так. Нам нужен двоичный файл!

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

Правильно, это просто конвертирует все в двоичный код. Но название гласит «по одному за раз». Нам нужно что-то, чтобы сохранить через несколько прогонов. Я знаю, давайте сделаем это функцией!

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

Подождите, это не поможет ... Хм, как мы можем отслеживать индекс бита, который должен быть выведен? Ох, ох, давайте иметь целое число, чтобы отслеживать.

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

Гм ... это всегда выводит первый бит. О, нам нужно увеличить трекер! О дерьмо, Python не допускает изменения целых чисел в качестве аргументов по умолчанию. И назначения не являются выражениями в Python, поэтому вы не можете сделать это в лямбда-выражении. Хорошо, это невозможно в Python, дело закрыто.

... ну не совсем. Python делает позволяют списки в качестве аргументов по умолчанию должны быть изменены. (И это постоянно кусает программистов на Python.) Давайте использовать его длину!

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

Это все еще не изменяет трекер ... Мы можем добавить к нему что-нибудь, чтобы увеличить его длину ... Но как? Ну, у нас есть list.append. lst.append(1)эквивалентно lst += [1]. Большой!

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

Ой, это пропускает первый бит, потому что длина трекера равна 1, прежде чем бит будет выведен. Нам нужно уменьшить длину, где он используется.

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

Вот оно, ребята! Гольф это, и у вас есть мое решение!


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.