Супер складные номера

10

Мы уже определили число складывания здесь .

Но теперь мы собираемся определить супер складной номер. Число Super Folding - это число, которое, если его сложить достаточно раз, в конечном итоге достигнет единицы, меньшей степени двойки. Метод складывания немного отличается от вопроса с номером сложения.

Алгоритм сворачивания выглядит следующим образом:

  • Взять двоичное представление

    например, 5882

    1011011111010
    
  • Разлил его на три раздела. Первая половина, последняя половина и средняя цифра (если она имеет нечетное количество цифр)

    101101 1 111010
    
  • Если средняя цифра равна нулю, это число нельзя сложить

  • Обратный второй тайм и накладывается на первый тайм

    010111
    101101
    
  • Добавьте цифры на месте

    111212
    
  • Если в результате есть любые 2, в результате число не может быть сложено, иначе новое число является результатом алгоритма складывания.

Число - это число Super Folding, если его можно сложить в непрерывную цепочку единиц. (Все складные номера также являются супер складными номерами)

Ваша задача - написать код, который принимает число и выводит истинное значение, если число является числом Super Folding, и ложно в противном случае. Вы будете оцениваться по размеру вашей программы.

Примеры

+5200

Преобразовать в двоичный файл:

1010001010000

Разделить пополам:

101000 1 010000

Середина одна, поэтому мы продолжаем накладывать половинки:

000010
101000

Добавил их:

101010

Нет двойки, поэтому мы продолжим разделение пополам:

101 010

Fold:

010
101

111

Результат 111(7 в десятичной системе счисления), так что это число Super Folding Number.

Тестовые случаи

Первые 100 супер складных номеров:

[1, 2, 3, 6, 7, 8, 10, 12, 15, 20, 22, 28, 31, 34, 38, 42, 48, 52, 56, 63, 74, 78, 90, 104, 108, 120, 127, 128, 130, 132, 142, 150, 160, 170, 178, 192, 204, 212, 232, 240, 255, 272, 274, 276, 286, 310, 336, 346, 370, 400, 412, 436, 472, 496, 511, 516, 518, 524, 542, 558, 580, 598, 614, 640, 642, 648, 666, 682, 704, 722, 738, 772, 796, 812, 852, 868, 896, 920, 936, 976, 992, 1023, 1060, 1062, 1068, 1086, 1134, 1188, 1206, 1254, 1312, 1314, 1320, 1338, 1386, 1440, 1458, 1506, 1572, 1596]
Специальный охотник за гарфами
источник
2
Если я не ошибаюсь, как снова 3пробраться в тестовые случаи? Я не вижу, как его можно сложить, так как он распадается 1 1, сразу давая 2. Или вы говорите, что сбросить ноль также имеет значение?
Geobits
@geobits 3 должен быть там. Я проверил на этот раз;). Три - это 11, поэтому он получает только один в нулевых файлах
Ad Hoc Garf Hunter
Я думаю, что, возможно, стоит поместить заметку прямо вверху страницы, сразу после ссылки на другой вопрос о сгибании чисел, который указывает, что отдельные сгибы в этом вопросе будут использовать другой метод.
Джонатан Аллан

Ответы:

9

Вот мой первый выстрел в коде гольф:

Python 3, 167 байт

167 байт, если для отступа используются табуляции или одиночные пробелы

def f(n):
 B=bin(n)[2:];L=len(B);M=L//2
 if'1'*L==B:return 1
 S=str(int(B[:M])+int(B[:-M-1:-1]))
 return 0if(~L%2==0and'0'==B[M])or'2'in S else{S}=={'1'}or f(int(S,2))

Изменить: Благодаря всеобщей помощи ниже, приведенный выше код был уменьшен с исходного размера 232 байта!

Kapocsi
источник
1
Добро пожаловать в PPCG! Вы можете сохранить несколько байтов, удалив пробелы после :s и вернув 0и 1вместо Trueи False.
Стивен Х.
Спасибо, Стивен. Кроме того, я не уверен на 100%, что правильно посчитал длину байта.
Капоши
1
Я вижу 232 байта. Дайте мне секунду, и я могу попытаться сыграть в гольф немного дальше.
Стивен Х.
Я использовал это, чтобы измерить: bytesizematters.com
Kapocsi
1
@Kapocsi, bytesizematters.com считает переводы строк неверными. Сравните с mothereff.in , 5 цифр и 5 новых строк должны быть 10 байтов, а не 14, которые я получил на байтах ... его 232.
Линус
5

Java 7, 202 байта

boolean g(Integer a){byte[]b=a.toString(a,2).getBytes();int i=0,l=b.length,o=0,c,z=(a+1&a)==0?-1:1;for(;i<l/2&z>0;o+=o+c*2,z*=c>1|(l%2>0&b[l/2]<49)?0:1)c=b[i]+b[l-++i]-96;return z<0?1>0:z<1?0>1:g(o/2);}

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

С переносами строк:

boolean g(Integer a){
    byte[]b=a.toString(a,2).getBytes();
    int i=0,l=b.length,o=0,c,z=(a+1&a)==0?-1:1;
    for(;i<l/2&z>0;o+=o+c*2,z*=c>1|(l%2>0&b[l/2]<49)?0:1)
        c=b[i]+b[l-++i]-96;
    return z<0?1>0:z<1?0>1:g(o/2);
}
Geobits
источник
3

CJam , 47 44 байта

ri2b{_W%.+__0e=)\_,1>\0-X+:*3<*&}{_,2/<}w2-!

Попробуйте онлайн! или сгенерировать список супер сворачиваемых чисел до заданного числа.
Попытки игры в гольф можно увидеть здесь .


Код разбивается на следующие фазы:

ri2b                e# get input in binary
{                   e# While fold is legal
 _W%.+_             e#   "fold" the whole number onto itself
 _0e=)\             e#   count zeros and add 1 (I)
 _,1>\              e#   size check, leave 0 if singleton (II)*
 0-X+:*3<           e#   product of 2s, leave 0 if too many (III)
 *&                 e#   (II AND III) AND parity of I
}{                  e# Do
 _,2/<              e#   slice opposite to the actual fold**
}w                  e# End while
2-!                 e# return 1 if "fold" ended in all 2s

РЕДАКТИРОВАТЬ: Эта версия более или менее использует подход закона де Моргана к предыдущей версии.

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

** Если двоичное число супер сворачивается, его зеркальное отображение (с ведущими нулями, если необходимо) равно. Это экономит байт за взятие правой половины.

Линус
источник
2

JavaScript, 149 байт

f=(i,n=i.toString(2),l=n.length,m=l/2|0)=>/^1*$/.test(n)?1:/[^01]/.test(n)|!+n[m]&l?0:f(0,+n.slice(0,m)+ +n.slice(m+l%2).split``.reverse().join``+"")

Определяет рекурсивную функцию.

Объяснение:

f=(i                       //Defines the function: i is input
,n=i.toString(2)           //n is the current number
,l=n.length                //l is the length of the number,
,m=l/2|0)=>                //m is the index of the center character
/^1*$/.test(n)?1:          //returns 1 if the number is all ones
/[^01]/.test(n)            //returns 0 if the number has any chars other than 0 or 1
|!+n[m]&l?0:               //or if the middle char is 0
f(0,+n.slice(0,m)+ +n.slice(m+l%2).split``.reverse().join``+"")
                           //otherwise recurses using the first half of the number plus the second half
DanTheMan
источник
m=l>>1, /2/.test(n), n.slice(l-m)(Или ломтик перевернутое строку). Я думаю, что если вы переключите случаи неудачи и успеха, вы можете использовать /0/.test(n)?f(...):1.
Нил
2

JavaScript (ES6), 113 109 108 байт

f=(n,[h,...r]=n.toString(2),b='')=>++n&-n-n?h?f(2,r,r[0]?b+(h- -r.pop()):+h?b:2):!isNaN(n=+('0b'+b))&&f(n):1

Отформатировано и прокомментировано

f = (                               // given:
  n,                                // - n = integer to process
  [h, ...r] = n.toString(2),        // - h = highest bit, r = remaining low bits
  b = ''                            // - b = folded binary string
) =>                                //
  ++n & -n - n ?                    // if n is not of the form 2^N - 1:
    h ?                             //   if there's still at least one bit to process:
      f(                            //     do a recursive call with:
        2,                          //     - n = 2 to make the 2^N - 1 test fail
        r,                          //     - r = remaining bits
        r[0] ?                      //     - if there's at least one remaining low bit:
          b + (h - -r.pop())        //       append sum of highest bit + lowest bit to b
        : +h ? b : 2                //       else, h is the middle bit: let b unchanged
      )                             //       if it is set or force error if it's not
    : !isNaN(n = +('0b' + b)) &&    //   else, if b is a valid binary string:
      f(n)                          //     relaunch the entire process on it
  : 1                               // else: n is a super folding number -> success

демонстрация

f=(n,[h,...r]=n.toString(2),b='')=>++n&-n-n?h?f(2,r,r[0]?b+(h- -r.pop()):+h?b:2):!isNaN(n=+('0b'+b))&&f(n):1

// testing integers in [1 .. 99]
for(var i = 1; i < 100; i++) {
  f(i) && console.log(i);
}

// testing integers in [1500 .. 1599]
for(var i = 1500; i < 1600; i++) {
  f(i) && console.log(i);
}

Arnauld
источник
2

Perl, 71 70 байт

Включает +1 для -p

Дайте номер на STDIN

superfolding.pl:

#!/usr/bin/perl -p
$_=sprintf"%b",$_;s%.%/\G0$/?2:/.\B/g&&$&+chop%eg while/0/>/2/;$_=!$&
Тон Хоспел
источник
1

Python 2, 151 байт

f=lambda n,r=0:f(bin(n)[2:],'')if r<''else(r==''and{'1'}==set(n)or(n in'1'and f(r,'')+2)or n!='0'and'11'!=n[0]+n[-1]and f(n[1:-1],r+max(n[0],n[-1])))%2

ideone

Двухрекурсивная функция, которая принимает целое число nи возвращает 0или 1.

Переменная rподдерживается, чтобы позволить как результат свертывания, так и узнать, есть ли у нас в настоящее время: целое число (только первое); иметь новую двоичную строку, чтобы попытаться свернуть (внешний); или складываются (внутри).

На первом проходе nесть и целое число, которое есть <''в Python 2, поэтому рекурсия начинается с приведения к двоичной строке.

Следующее выполнение имеет, r=''и поэтому выполняется тест {'1'}==set(n)для проверки непрерывной строки 1s (RHS не может быть, {n}поскольку нам, возможно, понадобится передать эту точку позже, r=''и пустым, nкогда это будет словарь, который не равен {'1'}, множество).

Если это не выполняется, критерии внутреннего хвоста проверяются (даже если в этом нет необходимости): if n in'1'оценивает значение True, когда nявляется пустой строкой или одиночной 1, после чего начинается новая внешняя рекурсия, помещаемая rзатем свернутую двоичную строку в nи ''в r. Литерал 2добавляется к результату этого вызова функции, чтобы не допустить перехода к следующей части (справа от логического or), которая будет исправлена ​​позже.

Если это неверное значение (все ненулевые целые числа являются истинными в Python), критерии внешней рекурсии проверяются на: n!=0исключая случай со средним, 0а внешние два символа проверяются, они не суммируются 2путем конкатенации строк '11'!=n[0]+n[-1]; если они оба сохраняют значение true, внешние биты отбрасываются с nпомощью n[1:-1], а затем 1добавляется a , rесли существует один снаружи, иначе a 0is, используя тот факт, что '1'>'0'в Python с max(n[0],n[-1]).

Наконец добавление 2в каждой внутренней рекурсии корректируется с помощью %2.

Джонатан Аллан
источник
0

PHP, 113 байт

for($n=$argv[1];$n!=$c;$n=($a=$n>>.5+$e)|($b=$n&$c=(1<<$e/=2)-1))if($a&$b||($e=1+log($n,2))&!(1&$n>>$e/2))die(1);

выходит с ошибкой (кодом 1), если аргумент не является супер-складным, код 0другой. Беги с -r.
Ввод 0вернет истину (код 0).

сломать

for($n=$argv[1];            
    $n!=$c;                 // loop while $n is != mask
                            // (first iteration: $c is null)
    $n=                     // add left half and right half to new number
        ($a=$n>>.5+$e)      // 7. $a=left half
        |
        ($b=$n&             // 6. $b=right half
            $c=(1<<$e/=2)-1 // 5. $c=mask for right half
        )
)
    if($a&$b                // 1. if any bit is set in both halves
                            // (first iteration: $a and $b are null -> no bits set)
        ||                  // or
        ($e=1+log($n,2))    // 2. get length of number
        &
        !(1&$n>>$e/2)       // 3. if the middle bit is not set -> 1
                            // 4. tests bit 0 in length --> and if length is odd
    )
    die(1);                 // -- exit with error
Titus
источник
0

PHP, 197 байт

function f($b){if(!$b)return;if(!strpos($b,"0"))return 1;for($n="",$i=0;$i<($l=strlen($b))>>1;)$n.=$b[$i]+$b[$l-++$i];if($l%2&&!$b[$i]||strstr($n,"2"))return;return f($n);}echo f(decbin($argv[1]));

расширенный

function f($b){
    if(!$b)return; # remove 0
    if(!strpos($b,"0"))return 1; # say okay alternative preg_match("#^1+$#",$b)
    for($n="",$i=0;$i<($l=strlen($b))>>1;)$n.=$b[$i]+$b[$l-++$i]; #add first half and second reverse
    if($l%2&&!$b[$i]||strstr($n,"2"))return; #if middle == zero or in new string is a 2 then it's not a number that we search
    return f($n); #recursive beginning
}
echo f(decbin($argv[1]));

Истинные значения <10000

1, 2, 3, 6, 7, 8, 10, 12, 15, 20, 22, 28, 31, 34, 38, 42, 48, 52, 56, 63, 74, 78, 90, 104, 108, 120, 127, 128, 130, 132, 142, 150, 160, 170, 178, 192, 204, 212, 232, 240, 255, 272, 274, 276, 286, 310, 336, 346, 370, 400, 412, 436, 472, 496, 511, 516, 518, 524, 542, 558, 580, 598, 614, 640, 642, 648, 666, 682, 704, 722, 738, 772, 796, 812, 852, 868, 896, 920, 936, 976, 992, 1023, 1060, 1062, 1068, 1086, 1134, 1188, 1206, 1254, 1312, 1314, 1320, 1338, 1386, 1440, 1458, 1506, 1572, 1596, 1644, 1716, 1764, 1824, 1848, 1896, 1968, 2016, 2047, 2050, 2054, 2058, 2064, 2068, 2072, 2110, 2142, 2176, 2180, 2184, 2222, 2254, 2306, 2320, 2358, 2390, 2432, 2470, 2502, 2562, 2576, 2618, 2650, 2688, 2730, 2762, 2866, 2898, 2978, 3010, 3072, 3076, 3080, 3132, 3164, 3244, 3276, 3328, 3380, 3412, 3492, 3524, 3584, 3640, 3672, 3752, 3784, 3888, 3920, 4000, 4032,4095, 4162, 4166, 4170, 4176, 4180, 4184, 4222, 4318, 4416, 4420, 4424, 4462, 4558, 4674, 4688, 4726, 4822, 4928, 4966, 5062, 5186, 5200, 5242, 5338, 5440, 5482, 5578, 5746, 5842, 5986, 6082, 6208, 6212, 6216, 6268, 6364, 6508, 6604, 6720, 6772, 6868, 7012, 7108, 7232, 7288, 7384, 7528, 7624, 7792, 7888, 8032, 8128, 8191, 8202, 8206, 8218, 8232, 8236, 8248, 8318, 8382, 8456, 8460, 8472, 8542, 8606, 8714, 8744, 8814, 8878, 8968, 9038, 9102, 9218, 9222, 9234, 9248, 9252, 9264, 9334, 9398, 9472, 9476, 9488, 9558, 9622, 9730, 9760, 9830, 9894, 99848128, 8191, 8202, 8206, 8218, 8232, 8236, 8248, 8318, 8382, 8456, 8460, 8472, 8542, 8606, 8714, 8744, 8814, 8878, 8968, 9038, 9102, 9218, 9222, 9234, 9248, 9252, 9264, 9334, 9398, 9472, 9476, 9488, 9558, 9622, 9730, 9760, 9830, 9894, 99848128, 8191, 8202, 8206, 8218, 8232, 8236, 8248, 8318, 8382, 8456, 8460, 8472, 8542, 8606, 8714, 8744, 8814, 8878, 8968, 9038, 9102, 9218, 9222, 9234, 9248, 9252, 9264, 9334, 9398, 9472, 9476, 9488, 9558, 9622, 9730, 9760, 9830, 9894, 9984

Йорг Хюльсерманн
источник