Разборные двоичные числа

28

Если вы выразите некоторое положительное целое число в двоичном коде без ведущих нулей и замените каждое 1на a, (а каждое 0на a ), тогда совпадут ли все скобки?

В большинстве случаев они не будут. Например, 9 находится 1001в двоичном формате, который становится там ())(, где совпадают только первые две скобки.

Но иногда они будут совпадать. Например, 44 является 101100двоичным, что становится ()(()), где все левые скобки имеют соответствующие правые скобки.

Напишите программу или функцию, которая принимает положительное целое число из десяти целых чисел и печатает или возвращает истинное значение, если версия числа в двоичных скобках имеет все совпадающие скобки. Если это не так, выведите или верните ложное значение.

Самый короткий код в байтах побеждает.

Связанная последовательность OEIS.

Правдивые примеры ниже 100:

2, 10, 12, 42, 44, 50, 52, 56

Ложные примеры ниже 100:

1, 3, 4, 5, 6, 7, 8, 9, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 45, 46, 47, 48, 49, 51, 53, 54, 55, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
Кальвин Хобби
источник
10
Есть последовательность для всего ...
Арктур

Ответы:

8

TeaScript , 9 байтов 16 18 20 22 24

Сохранено 2 байта благодаря @ETHproductions

!x÷W(n,¢)

Ого. Это коротко. Использует подход @ xnor. Это будет использовать рекурсивную функцию replace ( W), которая заменит все 10равные ()ничем. Если строка пуста, она сбалансирована.


Используя версию TeaScript, созданную после публикации этого запроса, это может стать 7 байтов:

!x÷W(n)

Ungolfed

!xT(2)W(n,``)

объяснение

!      // NOT, returns true if empty string, else false
 xT(2)   // To binary
 W(n,``) // n is 10, reclusive replaces 10 or (), with nothing.
Downgoat
источник
1
Превосходно! Две вещи, которые могут помочь: 1) Если он ложный, когда поднимается, он уже ложный, так что вам не нужна первая тильда. 2) Я считаю, что ~--cэто ложь в том же сценарии, что и c--.
ETHproductions
@ETHproductions потрясающе, спасибо! Теперь я до 16 байтов
Downgoat
13

Pyth, 10 байт

!uscG`T.BQ

Попробуйте этот набор тестов в компиляторе Pyth.

Как это работает

              (implicit) Store the evaluated input in Q.
       .BQ    Return the binary string representation of Q.
 u            Reduce w/base case; set G to .BQ and begin a loop:
     `T         Return str(10) = "10".
   cG           Split G (looping variable) at occurrences of "10".
  s             Join the pieces without separators.
              Set G to the returned string.
              If the value of G changed, repeat the loop.
              This will eventually result in either an empty string or a
              non-empty string without occurrences of "10".
!             Return (and print) the logical NOT of the resulting string.
Деннис
источник
Я придумал эквивалент !u:G`Tk.BQ. Возможно, легче понять.
orlp
Да, это, конечно, более естественный выбор.
Деннис
8

Python2, 87 байт

try:exec"print 1,"+"".join(["],","["][int(c)]for c in bin(input())[2:])
except:print 0

Ужасная реализация, которая злоупотребляет синтаксическими ошибками.

orlp
источник
3
Это код гольф. Ужасный комплимент.
CorsiKa
8

JavaScript (ES6), 55 54 51 байт

n=>![...n.toString(d=2)].some(c=>(d+=c*2-1)<2)*d==2

Сохраненные байты благодаря @ Vɪʜᴀɴ и @xsot !

объяснение

n=>
  ![...n.toString(    // convert the input to an array of binary digits
    d=2)]             // d = current depth (+2)
      .some(c=>       // iterate through the digits
        (d+=c*2-1)    // increment or decrement the parenthesis depth
          <2          // if the depth goes negative, return false
      )*
        d==2          // if we finished at a depth of 0, return true
user81655
источник
1
Вы можете сохранить два байта, удалив ненужные f=. Вы также можете использовать use +cвместо c|0case для целого числа. Вы также можете использовать, (+c?d++:d--)что еще короче
Downgoat
@ Vɪʜᴀɴ Хорошо. Есть ли какое-то руководство относительно того, когда мне нужно использовать f=? Потому что многие другие JavaScript-ответы на сайте называют свои функции.
user81655
1
Обычно вам нужно дать имя функции только в том случае, если вызов требует от вас этого. В противном случае можно предположить, что с неназванными функциями все в порядке.
Алекс А.
В Firefox он запускается 11, trueкогда он должен вернутьсяfalse
Downgoat
2
Я не знаю javascript, но я попытался сократить несколько байтов, и это работает в chrome:n=>![...n.toString(d=2)].some(c=>(d+=c*2-1)<2)*d==2
xsot
7

Python 2, 45 байт

f=lambda n,i=1:i*n>0<f(n/2,i+(-1)**n)or n<i<2

Рекурсивная функция. Считывает двоичные цифры nс конца, сохраняя счет iтекущего уровня вложенности паренов. Если он падает ниже 0, отклонить. Когда мы дойдем до начала, проверяем, есть ли счет 0.

На самом деле, мы начинаем отсчет, i=1чтобы было легко проверить, упал ли он 0. Единственный случай успеха терминала - n==0и i==1, проверенный с n<i<2. Мы заставляем эту проверку произойти, если n==0, или если она iпадает 0, и в этом случае она автоматически завершается неудачей

feersum сэкономил два байта, реструктурировав нерекурсивные случаи с неравенствами к короткому замыканию.

XNOR
источник
3
Нуждается в более условном злоупотреблении. f=lambda n,i=1:n>0<i*f(n/2,i+(-1)**n) or n<i<2, по крайней мере, сохраняет 1.
Feersum
6

CJam, 11 байт

ri2b"}{"f=~

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

Поскольку непустые / пустые строки в CJam являются правдивыми / ложными, а напечатанный вывод всегда является строкой, он, вероятно, соответствует правилам. При добавленной стоимости еще 3 байта, в общей сложности 14 байтов , мы можем фактически оставить в стеке правдивую или ложную строку , которая будет напечатана:

Lri2b"}{"f=~]s

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

Тестовые прогоны

$ cjam <(echo 'ri2b"}{"f=~') <<< 52 2>&-; echo
{{}{}}
$ cjam <(echo 'ri2b"}{"f=~') <<< 53 2>&-; echo

$ cjam <(echo 'ri2b"}{"f=~') <<< 54 2>&-; echo

$ cjam <(echo 'ri2b"}{"f=~') <<< 55 2>&-; echo

$ cjam <(echo 'ri2b"}{"f=~') <<< 56 2>&-; echo
{{{}}}

Как это работает

ri          e# Read an integer from STDIN.
  2b        e# Push the array of its binary digits.
    "}{"f=  e# Replace 0's with }'s and 1's with {'s.
          ~ e# Evaluate the resulting string.
            e# If the brackets match, this pushes one or more blocks.
            e# If the brackets do not match, the interpreter crashes.

CJam, 15 байтов

ri2bs_,{As/s}*!

Попробуйте эту скрипку в интерпретаторе CJam или проверьте все тестовые случаи одновременно .

Как это работает

ri               Read an integer from STDIN.
  2b             Push the array of its binary digits.
    s            Cast to string.
     _,          Push the string's length.
       {    }*   Do that many times:
        As/        Split at occurrences of "10".
           s       Cast to string to flatten the array of strings.
              !  Push the logical NOT of the result.
Деннис
источник
1
черт возьми
6

Python, 51 байт

lambda n:eval("'0b'==bin(n)"+".replace('10','')"*n)

Анонимная функция. Оценивает выражение, которое выглядит как

'0b'==bin(n).replace('10','').replace('10','').replace('10','')...

Каждая замена удаляет все 10, что соответствует (). После того, как все замены были сделаны, функция возвращает, является ли то, что осталось, только двоичным префиксом 0b. Для nзамены более чем достаточно , так как kчисло -d занимает самое большее количество k/2шагов, а его значение больше 2**k.

XNOR
источник
4

Руби, 40

->i{n='%0b'%i;1while n.slice!'10';n<?0}

Простая обработка строк. Сбрасывает «10», пока не останется ни одного.

Не тот Чарльз
источник
4

Серьезно , 17 байтов

,;2@¡@`""9u$(Æ`nY

Выходы 0для ложных и 1истинных. Попробуйте онлайн .

Объяснение:

,      get value from stdin
;      dupe top of stack
2@¡    pop a: push a string containing the binary representation of a (swapping to get order of operands correct)
@      swap top two elements to get original input back on top
`""9u$(Æ` define a function:
  ""     push empty string
  9u$    push "10" (push 9, add 1, stringify)
  (      rotate stack right by 1
  Æ      pop a,b,c: push a.replace(b,c) (replace all occurrences of "10" in the binary string with "")
n      pop f,a: call f a times
Y      pop a: push boolean negation of a (1 if a is falsey else 0)
Mego
источник
4

Japt, 23 байта

Japt - это сокращенная версия Ja vaScri pt . переводчик

Us2 a e@+X?++P:P-- &&!P

Это напоминает мне, насколько далеко еще должен пройти Japt по сравнению с TeaScript. После обновления переводчика в следующие несколько дней я бы хотел добавить в «ярлыки» символы типа Vɪʜᴀɴ.

Как это работает

       // Implicit: U = input number, P = empty string
Us2 a  // Convert U to base 2, then split the digits into an array.
e@     // Assert that every item X in this array returns truthily to:
 +X?   //  If X = 1,
 ++P   //   ++P. ++(empty string) returns 1.
 :P--  //  Otherwise, P--. Returns false if P is now -1.
&&!P   // Return the final result && !P (true if P is 0; false otherwise).
       // Implicit: output final expression

Вскоре после этого испытания @ Vɪʜᴀɴ (теперь известный как @Downgoat) помог мне реализовать функцию рекурсивной замены, как Wв ответе на TeaScript. Это означает, что этот вызов теперь можно выполнить всего за 5 байтов:

!¢eAs  // Implicit: U = input integer, A = 10
 ¢     // Convert U to binary.
  eAs  // Recursively remove instances of A.toString().
!      // Return the logical NOT of the result (true only for the empty string).

Проверьте это онлайн!

ETHproductions
источник
3

Mathematica, 49 байтов

(#~IntegerDigits~2//.{x___,1,0,y___}:>{x,y})=={}&
alephalpha
источник
Я не могу читать Mathematica. Пояснения, пожалуйста? :)
Конор О'Брайен
@ CᴏɴᴏʀO'Bʀɪᴇɴ Преобразуйте число в основание 2 (в виде списка), затем несколько раз удалите 1,0из списка и проверьте, является ли результат пустым списком.
алефальфа
3

Октава, 48 байт

@(a)~((b=cumsum(2*dec2bin(a)-97))(end)|any(b<0))
alephalpha
источник
3

C ++, 104 94 байта

#include<iostream>
int n,c;int main(){for(std::cin>>n;n&c>=0;n>>=1)c+=n&1?-1:1;std::cout<<!c;}

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

объяснение

  • Объявления вне main инициализируются до 0.
  • Чтение десятичного числа неявно преобразуется в двоичное, потому что это компьютер.
  • Мы проверяем биты / скобки справа налево из-за n>>=1.
  • c+=n&1?-1:1ведет учет открытых скобок ).
  • n&c>=0 останавливается, когда остаются только начальные 0 или закрывающая скобка больше, чем открывается.
Линус
источник
3

Haskell, 49 46 байтов

0#l=l==1
_#0=2<1
n#l=div n 2#(l+(-1)^n)
f=(#1)

Пример использования: f 13-> False.

Я отслеживаю уровень вложенности, lкак и многие другие ответы. Тем не менее, «сбалансированный» случай представлен 1, как и «более- )чем- (» случай 0.

PS: нашел корректировку уровня вложенности l+(-1)^nв ответе xnor .

Ними
источник
signumКажется слишком сложным, как насчет просто _#0=1<0?
xnor
@xnor: да, спасибо.
Ними
Почему не l>0вместо l==1?
Майкл Кляйн
@MichaelKlein: потому что только l==1сбалансировано. Если l>1круглые скобки не разбиты.
Ними
@nimi Понятно, я неправильно понял, как это работает
Майкл Кляйн
3

Python 2, 60 57 56 55 53 52 50 49 байтов

n=input()
i=1
while i*n:i+=1|n%-2;n/=2
print i==1

Спасибо xnor за сохранение двух байтов и feersum за доведение окончательного числа байтов до 49!

объяснение

Входной номер, nобрабатывается от его младшего значащего бита. iэто счетчик, который отслеживает количество 0 и 1. Обратите внимание, что он инициализирован 1для сохранения байта. Цикл будет прерван до того, как nдостигнет 0, если число 1 превысит число 0 ( i<=0).

Для того, чтобы скобки были сбалансированы, необходимы два условия:

  • Количество 0 и 1 равно (то есть i==1)
  • Число 1 никогда не превышает числа 0 во время этого процесса (то есть цикл не прерывается преждевременно n==0). Изменить: я понял, что это условие не является необходимым, так как iдолжно быть не положительным, если n!=0так достаточно предыдущего условия.
xsot
источник
Если iи nнеотрицательны, то i==n==0есть i+n==0.
Orlp
iможет быть отрицательным, если цикл прерывается преждевременно.
xsot
На самом деле, i|n==0всегда должно работать.
orlp
Отличное предложение, эта линия выглядит лучше.
xsot
while i*nдолжен работать
xnor
3

JavaScript ES5, 118 87 85 82 77 байт

Интересная техника на мой взгляд. Минус, черт возьми, благодаря @ETHproductions и @NotthatCharles

function p(x){x=x.toString(2);while(/10/.test(x))x=x.replace(10,"");return!x}

JavaScript ES6, 77 57 56 54 байта

-21 байт для ETHпродукции.

x=>[...x=x.toString(2)].map(_=>x=x.replace(10,""))&&!x
Конор О'Брайен
источник
Мне нравится перевод в скобках. Однако, если вы оставите это как 1 и 0, это будет немного короче:function p(x){x=x.toString(2);r=/10/;while(x.search(r)>=0){x=x.replace(r,"")}return!x}
ETHproductions
@ETHproductions Хорошая мысль! Я думаю, что оставлю другой код внизу, мне очень нравится алгоритм ^ _ ^ Спасибо, приятель!
Конор О'Брайен
Версия ES6 все еще может быть удачной игрой: x=>([...x=x.toString(2)].map(_=>x=x.replace(/10/,"")),!x)хитрость заключается в том, чтобы переместить цикл while в a .map, поскольку на входе никогда не бывает больше десяти, чем его длина.
ETHproductions
@ETHproductions Еще раз спасибо ^ _ ^ Хороший трюк с map.
Конор О'Брайен
Нет проблем :) Кстати, другой байт можно сохранить с помощью трюка, который edc65 использует постоянно: x=>[...x=x.toString(2)].map(_=>x=x.replace(/10/,""))&&!xIDK, если он может стать короче, хотя.
ETHproductions
2

D 209 170 байт

import std.stdio;import std.format;import std.conv;void main(char[][]a){string b=format("%b",to!int(a[1]));int i;foreach(c;b){i+=c=='1'?1:-1;if(i<0)break;}writeln(i==0);}

Это делает именно то, что он должен делать без каких-либо дополнений или преимуществ.

фаза
источник
2

C 67 байт

n;main(i){for(scanf("%d",&n);n*i;n/=2)i+=1-n%2*2;putchar(48+!~-i);}

В значительной степени порт моего представления Python.

xsot
источник
2

Пролог, 147 байт

b(N,[X|L]):-N>1,X is N mod 2,Y is N//2,b(Y,L).
b(N,[N]).
q([H|T],N):-N>=0,(H=0->X is N+1;X is N-1),q(T,X).
q([],N):-N=0.
p(X):-b(X,L),!,q(L,0).

Как это работает

b(N,[X|L]):-N>1,X is N mod 2,Y is N//2,b(Y,L).
b(N,[N]).

Преобразует десятичное число N в двоичное представление в виде списка (в обратном порядке). Смысл:

b(42,[0,1,0,1,0,1]) is true

Затем:

q([H|T],N):-N>=0,(H=0->X is N+1;X is N-1),q(T,X).
q([],N):-N=0.

Повторяется по списку [H | T], увеличивая N, если элемент head равен 0, в противном случае его уменьшают.
Если N в любой точке становится отрицательным или если N в конце не равно 0, возвращает false, иначе true.

Разрез в

p(X):-b(X,L),!,q(L,0).

Есть ли, чтобы предотвратить откат и найти недвоичные решения для b (N, [N])?

Тестирование
Попробуйте онлайн здесь.
Запустите его с помощью запроса:

p(42).
Emigna
источник
2

PowerShell, 106 байт

param($a)$b=[convert]::ToString($a,2);1..$b.Length|%{if($b[$_-1]%2){$c++}else{$c--}if($c-lt0){0;exit}};!$c

Не собираюсь выигрывать соревнования на самую короткую длину, это точно. Но эй, по крайней мере, это бьет Java?

Использует очень длинный вызов .NET [convert]::ToString($a,2)для преобразования нашего входного номера в строку, представляющую двоичные цифры. Затем мы за цикл по этой строке с 1..$b.length|%{..}. В каждом цикле, если наша цифра является 1(оценивается с помощью, %2а не -eq1для сохранения пары байтов), мы увеличиваем наш счетчик; иначе мы уменьшаем его. Если мы когда-либо достигнем отрицательного значения, это означает, что их было больше, )чем (встречалось, поэтому мы выводим 0и exit. Как только мы закончим цикл, $cбудет либо одно, 0либо какое-то число >0, поэтому мы берем логическое, а не !его число, которое получает вывод.

Это имеет причуду вывода, 0если парены не соответствуют, потому что у нас больше ), но вывод, Falseесли парены не соответствуют, потому что у нас больше (. По сути, функционально эквивалентные ложные высказывания, просто интересные. Если все символы совпадают, выходы True.

AdmBorkBork
источник
Да конечно. (Ну, если я смогу устранить ноющее сомнение в том, что я решаю не ту проблему, я это сделаю).
TessellatingHeckler
1

GNU Sed (с расширением eval), 27

s/.*/dc -e2o&p/e
:
s/10//
t

У Седа на самом деле нет четкого представления о правдивости и ложности, поэтому здесь я утверждаю, что пустая строка означает правдивость, а все остальные строки означают ложь.

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

GNU Sed (с расширением eval), 44

s/.*/dc -e2o&p/e
:
s/10//
t
s/.\+/0/
s/^$/1/

Это выводит 1 для истины и 0 в противном случае.

Цифровая травма
источник
1

𝔼𝕊𝕄𝕚𝕟 (ESMin), 21 символ / 43 байта

ô⟦ïßḂ]Ĉ⇀+$?⧺Ḁ:Ḁ‡)⅋!Ḁ)

Try it here (Firefox only).

Обратите внимание, что здесь используются переменные, предопределенные для чисел (в частности, 2 и 0). Есть предопределенные числовые переменные от 0 до 256.

19 символов / 40 байтов, неконкурентный

⟦ïßḂ]Ĉ⇀+$?⧺Ḁ:Ḁ‡)⅋!Ḁ

Try it here (Firefox only).

Решили реализовать неявный вывод ... Однако предыдущие формы вывода все еще поддерживаются, поэтому вы получаете несколько вариантов вывода!

Mama Fun Roll
источник
потому что каждый измеряет количество символов
фаза
1

Java, 129 131 байт

boolean T(int i){int j=0,k=0;for(char[]a=Integer.toString(i,2).toCharArray();j<a.length&&k>=0;j++){k+=a[j]=='1'?1:-1;}return k==0;}

Вероятно, может быть сокращено. Объяснение, чтобы прийти. Спасибо Geobits за 4 байта!

GamrCorps
источник
Можно ли сочетать int k=0;с int j=0;?
ETHproductions
Нет, j является внутренней переменной в цикле for, и на нее нельзя ссылаться вне ее.
GamrCorps
Вы должны иметь возможность комбинировать другой способ: int k=0,j=0;for(...затем вы можете поместить char[]объявление внутри инициализатора цикла, чтобы также сохранить точку с запятой.
Geobits
Большая проблема в том, что это дает ложные срабатывания. Например, он возвращает true для 9, 35, 37, 38 .
Geobits
@ Geobits упс, я даже не осознавал, что исправлю, когда у меня будет шанс.
GamrCorps
1

C ++, 61 байт

Я думаю, что текущий ответ C ++ неверен: он возвращает истинное значение для всех четных чисел, например, 4. Отказ от ответственности: я не смог использовать упомянутый компилятор, поэтому я использовал g ++ 4.8.4. Проблема заключается в использовании двоичного оператора AND вместо логического AND, который используется для раннего прерывания, когда количество закрывающих скобок превышает количество открывающих скобок. Этот подход может работать, если trueон представлен в виде слова с полностью истинным битовым шаблоном. В моей системе и, возможно, в большинстве других систем trueэто эквивалентно 1; только один бит верен. Также n/=2короче чем n>>=1. Вот улучшенная версия как функция:

int f(int n,int c=0){for(;c>=0&&n;n/=2)c+=n&1?-1:1;return c;}
vysar
источник
0

𝔼𝕊𝕄𝕚𝕟 (очень неконкурентоспособно), 6 символов / 8 байт

!ïⓑĦⅩ

Try it here (Firefox only).

Я решил вернуться к этой проблеме через очень, очень долгое время. Got стало намного лучше.

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

объяснение

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

Mama Fun Roll
источник
0

C # 98 байт

bool f(int m){int i=0;foreach(char s in Convert.ToString((m),2)){if(s=='1')i+=2;i--;}return i==0;}

открыт для любых предложений. мне нравится этот вызов, даже если он старый

downrep_nation
источник