Повторний байтовий лічильник


19

Ваше завдання полягає в тому, щоб написати непорожню програму / функцію підрахунку байт L , який, коли повторні М раз, перевіряє , є чи дана цілим позитивним числом N дорівнює L × M .

Теоретично вам слід підтримувати довільну кількість повторень (довільне додатне ціле значення M ), але це добре, якщо через мовні обмеження він не може працювати над певним порогом. Читання вихідного коду вашої програми або отримання доступу до інформації про неї категорично заборонено .

Для забезпечення виводу слід вибрати послідовне значення для одного з станів (або truthy або falesy), і використовувати будь-який інший (не обов'язково послідовний) можливий вихід для іншого стану ( обговорення ).

Ваші відповіді будуть оцінені відповідно до початкової довжини програми L (у байтах), при цьому менше байтів буде кращим.

Приклад

Скажімо, ваша (початкова) програма така ABCDE. Потім:

  • ABCDE(1 повторення) слід перевірити, чи вхід дорівнює 5 .
  • ABCDEABCDE(2 повторення) слід перевірити, чи вхід дорівнює 10 .
  • ABCDEABCDEABCDE(3 повторення) слід перевірити, чи вхід дорівнює 15 . І т.д. ...

Оцінка цього зразкового коду склала б 5 , оскільки початкове джерело - 5 байт.


Просто для уточнення: вихідний код довжини, Lз'єднаний після себе, Mповинен повертати, чи Nрівний його вхідL*M ?

Відповіді:


12

Желе , 1 байт

Вихід 0 для матчу, не нульовий для не збігу.

Спробуйте в Інтернеті!

Як це працює

Це дає перевагу надто ліберальному формату виводу. Повторення M разів просто зменшує вхідний M разів, тому результат буде нульовим тоді і лише тоді, коли вхід LM , де L = 1 .


Боже, я не бачив, щоб це відбувалося ... ( inb4 всі переносять це на інші езоланг ... )
Містер Xcoder

Я мав на увазі 0-байтну відповідь, але, так, квіне . : P
Erik the Outgolfer

Моя перша думка. Побитий за 23 хвилини :(
Хулдрасетс на'Барія


8

Сітківка , 21 20 байт

\d+
*
^$
_
^_{20}

_

Спробуйте в Інтернеті! Просто повторіть частину у вікні Код, щоб побачити, як вона обробляє кратні.

Дає 0правильні кратні чи додатні цілі числа для всього іншого.

Пояснення

Розглянемо спочатку єдину програму:

\d+
*

Це перетворює десяткове число в одинарне (використовуючи _як одинарну цифру).

^$
_

Якщо рядок порожній (що не може статися в цей момент, оскільки вхід гарантовано є позитивним), ми замінюємо його одиничним _.

^_{20}

Тепер ми позбулися перших 20 підкреслень. Якщо вхід був 20, це призводить до порожнього рядка.

_

І, нарешті, ми підраховуємо кількість підкреслень у результаті, що дорівнює нулю, якщо вхід був 20.


Тепер, що відбувається, коли ми повторимо вихідний код. Оскільки ми не вставляємо стрічку під час приєднання до програм, перший рядок піде прямо в кінці останнього рядка, ми отримаємо це, коли подвоїмо програму:

\d+
*
^$
_
^_{20}

_\d+
*
^$
_
^_{20}

_

Тепер, замість підрахунку підкреслених, ми закінчуємо наступним етапом:

_\d+
*

Цей етап нічого не робить, тому що в робочому рядку більше цифр немає, тому регулярний вираз не може відповідати.

^$
_

Зараз цей етап стає актуальним. Якщо вхід був меншим кратним 20, рядок спорожнюється попередньою копією вихідного коду. У цьому випадку ми перетворюємо це на єдине підкреслення, яке, як ми знаємо, ніколи не може бути перетворене в порожню рядок нашою програмою. Таким чином , ми гарантуємо , що тільки в М - е множинний приймаються (і не всі кратні аж до М - го).

^_{20}

Знімаємо перші 20 підкреслень ще раз. Таким чином, M повторення вихідного коду видалять 20M підкреслення, якщо це можливо.

_

І коли ми доходимо до кінця програми, ми все ще підраховуємо підкреслення, так що дійсні введення дають нуль.


6

32-бітний фрагмент машинного коду x86, 1 байт

48                      dec    eax

Введення в EAX, вихід у EAX: 0 для істинного, не нульове значення для помилкового. (Також прапор ZF залишається встановленим як істинний, невідомий для помилкового, щоб ви могли je was_equal). Як "бонус", ви не повинні турбуватися про обгортання; 32-розрядний x86 може адресувати лише 4 Гбіт пам'яті, тому ви не можете зробити M достатньо великим, щоб обернутись навколо і знайти 1 == 2**32 + 1щось подібне.

Щоб зробити функцію дзвінка, додайте 0xC3 retінструкцію після повторення 0x48M разів. (Не зараховується до загальної кількості, оскільки для багатьох мов потрібно повторювати лише функціональне тіло або вираз, щоб мати можливість змагатися).

Викликається з GNU C за допомогою прототипу функції атрибута x86 функції __attribute__((regparm(1))) int checkeqM(int eax); GNU Cregparm , наприклад -mregparm, використовує EAX для передачі першого цілого аргументу.

Наприклад, ця повна програма займає 2 аргументи, а JITs M копіює інструкцію + a retв буфер, а потім викликає її як функцію. (Потрібна виконувана купа; компілювати з gcc -O3 -m32 -z execstack)

/******* Test harness: JIT into a buffer and call it ******/
// compile with gcc -O3 -no-pie -fno-pie -m32 -z execstack
// or use mprotect or VirtualProtect instead of -z execstack
// or mmap(PROT_EXEC|PROT_READ|PROT_WRITE) instead of malloc

// declare a function pointer to a regparm=1 function
// The special calling convention applies to this function-pointer only
// So main() can still get its args properly, and call libc functions.
// unlike if you compile with -mregparm=1
typedef int __attribute__((regparm(1))) (*eax_arg_funcptr_t)(unsigned arg);

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    if (argc<3) return -1;
    unsigned N=strtoul(argv[1], NULL, 0), M = strtoul(argv[2], NULL, 0);

    char *execbuf = malloc(M+1);   // no error checking
    memset(execbuf, 0x48, M);     // times M  dec eax
    execbuf[M] = 0xC3;            // ret
    // Tell GCC we're about to run this data as code.  x86 has coherent I-cache,
    // but this also stops optimization from removing these as dead stores.
    __builtin___clear_cache (execbuf, execbuf+M+1);
     //   asm("" ::: "memory");  // compiler memory barrier works too.

    eax_arg_funcptr_t execfunc = (eax_arg_funcptr_t) execbuf;
    int res = execfunc(N);
    printf("%u == %u  =>  %d\n", N,M, res );
    return !!res;   // exit status only takes the low 8 bits of return value
}

виконувані файли, що не належать до PIE , завантажуються нижче у віртуальну пам'ять; може зробити більший суміжний молоток.

$ gcc -g -O3 -m32 -no-pie -fno-pie -fno-plt -z execstack coderepeat-i386.c
$ time ./a.out 2747483748 2747483748   # 2^31 + 600000100 is close to as big as we can allocate successfully
2747483748 == 2747483748  =>  0

real    0m1.590s     # on a 3.9GHz Skylake with DDR4-2666
user    0m0.831s
sys     0m0.755s

$ echo $?
0

 # perf stat output:
       670,816      page-faults               #    0.418 M/sec                  
 6,235,285,157      cycles                    #    3.885 GHz                    
 5,370,142,756      instructions              #    0.86  insn per cycle         

Зверніть увагу , що GNU C не підтримує об'єкт розміром більше ptrdiff_t(32-розрядний), але mallocі memsetзробити ще роботи, так що ця програма успішно.

Фрагмент машинного коду великого пальця ARM, 2 байти

 3802            subs    r0, #2

Перший аргумент r0і значення повернення в r0- це стандартна конвенція про виклик ARM. Тут також встановлюються прапори ( sсуфікс). Кумедний факт; версія, що не встановлює флаг, sub- це 32-бітова інструкція.

Інструкція повернення, яку потрібно додати, - це bx lr.

Фрагмент машинного коду AArch64, 4 байти

d1001000        sub     x0, x0, #0x4

Працює для 64-бітних цілих чисел. Введення / виведення в x0, відповідно до стандартного режиму виклику. int64_t foo(uint64_t);

AArch64 не має режиму великого пальця (поки що), тому 1 інструкція - це найкраще, що ми можемо зробити.


Зверніть увагу на всіх, хто стикається з цим: дзвінок необхідний __builtin___clear_cacheлише тому, що ви виконуєте пам'ять, з якої ви отримали malloc. Якщо ви отримали пам'ять mmapзамість цього, оптимізація не відбувається.
Джозеф Сибл-Відновити Моніку

4

V , 16 (або 1) байт

Нудна відповідь:

<C-x>

один байт.

Менш нудна відповідь:

uÓ^$/0
16Ø^a$

Спробуйте в Інтернеті!

Hexdump:

00000000: 75d3 5e24 2f30 0a31 3601 d85e 1261 240a  u.^$/0.16..^.a$.

Я фактично написав це приблизно через 5 хвилин після виходу виклику. Щоб зафіксувати цю жахливу купу коду спагетті, яку я називаю мовою, знадобилося 30 хвилин .





2

Мозок-Флак , 24 байти

({}[(((()()()){}){}){}])

Спробуйте в Інтернеті!

Повертається 0за рівне, а щось інше - не рівне.

Як це працює:

({} #pop the top of the stack
  [(((()()()){}){}){}] #subtract 24
) #push the result.

Цей час виконання коду nбуде відніматися n * 24з введення, даючи 0 лише тоді, коли введення = n*24.



2

TI-Basic (83 серія), 4 байти

:Ans-4

Здійснює введення в Ans: наприклад, ви можете ввести 17:prgmCODEGOLFце запуск із введенням 17. Виводить (і повертає Ans) значення, 0якщо вхід дорівнює L × M , а ненульове значення - в іншому випадку.

Зауважте, що :це частина коду, тому якщо ви вводите це в редактор програми, ви повинні побачити

PROGRAM:CODEGOLF
::Ans-4

якщо ввести його один раз і

PROGRAM:CODEGOLF
::Ans-4:Ans-4:An
s-4

якщо ввести його тричі.



1

Befunge-98 , 15 байт

]#<@.-&+
>fv
v+

Спробуйте в Інтернеті!

Спробуйте вдвічі!

Використовує 0 для рівних і все інше для нерівних.

Пояснення:

Цей код, повторений багато разів, буде виглядати приблизно так:

]#<@.-&+
>fv
v+]#<@.-&+
>fv
v+]#<@.-&+
>fv
 .
 .
 .
v+]#<@.-&+
>fv
v+
  1. ]правий поворот. Відсилає IP вниз.

  2. >рухатися на схід. Відправляє IP-адресу право.

  3. f push 16.

  4. vрухатися на південь. Відсилає IP вниз. Якщо це востаннє, перейдіть до кроку 8.

  5. ]правий поворот. Надсилає IP зліва.

  6. +додати. Додає 16 у верхній частині стека.

  7. vрухатися на південь. Відсилає IP вниз. Перейдіть до кроку 2.

  8. <рухатися на захід. Відправте IP зліва.

  9. #пропустити. перестрибнути ]і завернути до кінця.

  10. +додати. Додає 16 у верхній частині стека.

  11. &вхід. Натисніть номер від користувача.

  12. -відняти. отримати різницю суми, над якою ми працювали, та вклад.

  13. .друк. Роздрукуйте результат.

  14. @ кінець.



1

Вугілля деревне , 13 байт

PI⁼Iθ×¹³L⊞Oυω

Спробуйте в Інтернеті! На підставі моєї відповіді я подвоюю джерело, ви подвоюєте вихід! Пояснення:

         ⊞Oυω   Push empty string to predefined empty list
        L       Take the length
     ×¹³        Multiply by 13
  ⁼Iθ           Compare to the input
 I              Cast to string
P               Print without moving the cursor

Вдається виводити 1на трибуну і 0на помилку . Наступні повтори порівнюють вхід проти 13, 26, 39, і 52т.д. , але кожен раз , коли відповідь надпечаткі так тільки остаточну відповідь видно.


1

JavaScript ES6, 32 байти

((f=k=>n=>n>0?n==k:f(k+32))(32))

якщо true - 0, а false - інші, 31 байт

(f=k=>n=>n>0?n-k:_=>f(k+_))(31)

console.log([
    ((f=k=>n=>n>0?n==k:f(k+32))(32)) (31),
    ((f=k=>n=>n>0?n==k:f(k+32))(32)) (32),
    ((f=k=>n=>n>0?n==k:f(k+32))(32)) (33),
    ((f=k=>n=>n>0?n==k:f(k+32))(32)) (64),
    ((f=k=>n=>n>0?n==k:f(k+32))(32))((f=k=>n=>n>0?n==k:f(k+32))(32)) (32),
    ((f=k=>n=>n>0?n==k:f(k+32))(32))((f=k=>n=>n>0?n==k:f(k+32))(32)) (63),
    ((f=k=>n=>n>0?n==k:f(k+32))(32))((f=k=>n=>n>0?n==k:f(k+32))(32)) (64),
    ((f=k=>n=>n>0?n==k:f(k+32))(32))((f=k=>n=>n>0?n==k:f(k+32))(32))((f=k=>n=>n>0?n==k:f(k+32))(32)) (96)
]);


1

MIPS, 4 байти

Використовується $a0як аргумент і повернене значення.

0x2084fffc    addi $a0, $a0, -4

MIPS, 8 байт (використовуючи конвенцію про дзвінки MIPS)

0x2084fff8    addi $a0, $a0, -8
0x00041021    move $v0, $a0

x86, 5 байт

Це моя перша відповідь x86, тому відгуки вітаються. В якості першого аргументу використовується умова _fastcall з ecx.

83 e9 05                sub    $0x5,%ecx
89 c8                   mov    %ecx,%eax

Пітер Кордес має 1-байтне рішення у коментарях.


Коментар Brainfuck : Важка частина полягає в тому, щоб повернути єдине значення. Інакше щось подібне було б легко.

- >,[-<->] < .

1
Ваш кодовий фрагмент x86 був би однакового розміру для 32-бітових цілих чисел, не потрібно обмежуватись 8. Але якщо ви використовували власну конвенцію виклику (arg в AL, вилучення деінде,), ви можете використовувати 2-байтовий спеціальний AL кодування sub $4, %al/ mov %al, %dl. Або все-таки поверніться в AL / EAX, і тоді ви отримаєте рішення Денніса, з dec %eax(1 байт у 32-бітному режимі). І так, користувацькі конвенції про дзвінки чудово підходять для асм. Це asm, а не просто "asm, який легко зателефонувати з C"; Реальний код, написаний у ASM, використовує власні умови викликів, коли це допомагає, тому це цілком виправдано.
Пітер Кордес

1
Нормальна умова виклику ARM - це перший аргумент, в r0якому також відбувається вилучення, тому великий палець sub r0, #2- 2 байти.
Пітер Кордес

1
Зверніть увагу, що жодна з цих функцій не є функціями : для їх retвиклику потрібен кінець блоку повторень. Зазвичай я включаю кількість retбайтів для моїх відповідей на x86 на ASM. Але я думаю, призначати правила тут лише тілом функції має сенс, інакше багато мов взагалі не можуть змагатися.
Пітер Кордес

1
(nvm, це не залишає відновлення у% al). xchg %eax, %ecx/ sub $4, %al/ xchg %eax, %ecxстановить 4 байти і відповідає умові _fastcall. Використання AL, im8 та коротких кодувань xchg-з-eax часто корисні для гольфу з кодом.
Пітер Кордес

1
Зазвичай я використовую, objdump -drwC -Mintelщоб отримати шістнадцятковий байт машинного коду. add r32, imm8також 3 байти: opcode + ModR / M + imm8. Усі інструкції, які можуть прийняти im32, мають альтернативний код коду, який має розширений знак8. Дивіться, наприклад, felixcloutier.com/x86/ADD.html ; всі "класичні" інструкції ALU (але не MOV), які датуються 8086 роком, мають усі ці кодування, включаючи спеціальні AL / AX / EAX без модуля / м, просто op + imu8 / 16/32. Ця відповідь має приклади
Пітер Кордес,

1

Октава: 23 байти

+23;[ans,i]((N==ans)+1)

Якщо N = L * M, вираз повертається 0+i(тобто чисто уявне число), інакше вираз призводить до складного числа з реальною складовою.

Для трохи приємнішого результату ціною додаткового байта:

+24;[ans,-1]((N==ans)+1)

Якщо N = L * M, вираз повертається -1, інакше додатне число.

Демонстрація:

N=48;
+24;[ans,-1]((N==ans)+1)                                                 #>> 24 
+24;[ans,-1]((N==ans)+1)+24;[ans,-1]((N==ans)+1)                         #>> -1
+24;[ans,-1]((N==ans)+1)+24;[ans,-1]((N==ans)+1)+24;[ans,-1]((N==ans)+1) #>> 23

PS, ви можете отримати той самий результат, +24;if N==ans;-1;end;ansале і кількість рахунків однакова


1

Луа, 56 46 байт

a=(a or io.read())-46io.write(a<=0 and a or"")

Виводить 0 (без зворотного нового рядка), якщо він рівний, або нічого, або ряд від'ємних чисел (з попереднім нулем у деяких випадках), якщо вони не рівні.

Поодинці: Спробуйте в Інтернеті!

Неодноразово багато разів: спробуйте в Інтернеті!

Пояснення

a=(a or io.read())-46

Під час першої ітерації (коли aвона ще не була визначена і тому є nil), встановлюється aчисло, взятое з введення, інакше до себе. В обох випадках 46 віднімається від a.

io.write(a<=0 and a or"")

Це просто друкує, aякщо воно менше (щоб подбати про випадки, коли вхід був більший за загальну довжину) або дорівнює нулю, а порожній рядок - інакше.

-10 байт для запам'ятовування того, що Lua автоматично перетворює числа і рядки. Уопс.


0

JavaScript (ES6), 47 байт

Це використовує той же метод , як Benoit Esnard в цій відповіді (від мене подвійне джерело, ви подвоїти вихід! ).

Друкує 0, якщо n = 47 * M , або не-нульове значення в іншому випадку.

n=prompt(setTimeout`alert(n)`)-47/*
n-=47//*///

Демо для M = 1

n=prompt(setTimeout`alert(n)`)-47/*
n-=47//*///

Демо для M = 2

n=prompt(setTimeout`alert(n)`)-47/*
n-=47//*///n=prompt(setTimeout`alert(n)`)-47/*
n-=47//*///


0

Мозок-Флак , 24 байти

({}[(((()()()){}){}){}])

Спробуйте в Інтернеті!

Просто відніміть 24 від введення. Вихідні дані 0для істинних і все інше для помилкових.

Мозок-Флак , 68 байт

{<>}<>(({}[((((()()()()){}){}()){}){}])<>{})((){[()](<{}<>>)}{}<>{})

Спробуйте в Інтернеті!

Цей складніший, він виводить 1для істинного та 0хибного.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.