Определите, делится ли целое число на 3


20

Ваша цель - определить, делится ли число на 3 без использования условных выражений. На входе будет 8-битное число без знака от 0 до 255. Творчество приветствуется!

Вам разрешено использовать ТОЛЬКО

  • Равенство / Неравенство ( ==, !=, >, <, >=, <=)

  • Арифметика ( +, -, x)

  • Логические операторы ( !не, &&и, || или)

  • Побитовые операторы ( ~не, &и, |или, ^исключающий, <<, >>, >>>арифметические и логические левые и правые сдвиги)

  • Константы (было бы лучше, если бы вы держали эти маленькие)

  • Переменная присваивание

Выведите, 0если false, 1если true.

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


@GregHewgill Моя опечатка, это должно быть 8-битное число.
Qwr

2
Разрешено ли использовать только вышеуказанные операторы? В противном случае по модулю это будет слишком просто.
Jwosty

Кроме того, как насчет поиска в таблице?
Грег Хьюгилл

3
Можете ли вы уточнить, что вы подразумеваете под безусловными? Это ограничено утверждениями IF, или это относится и к таким вещам, как циклы?
Руслан

1
@Ruslan Вы можете использовать только выше.
Qwr

Ответы:


31

C - 2 жетона

int div3(int x) {
    return x * 0xAAAAAAAB <= x;
}

Кажется, работает до 2 31 -1.

Кредиты zalgo("nhahtdh")для мультипликативной обратной идеи.


1
+1. Был немного озадачен тем, как <=работает, и вспомнил, что 0xAAAAAAAB принимается за unsigned intтип, поэтому результат умножения не подписан.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Операторы неравенства @DigitalTrauma разрешены, а не запрещены
aditsu

@aditsu Ой! Мне нужно иногда читать внимательнее! +1 отличный ответ!
Цифровая травма

@aditsu, извини, я нуб, как именно это работает?
Kartik_Koro

2
@Kartik_Koro 0xAAAAAAAB * 3 == 1 из-за переполнения, поэтому для любого типа int x, x * 0xAAAAAAAB * 3 == x. Также y * 3 имеет разные значения для разных y, поэтому y = x * 0xAAAAAAAB должен быть единственным y таким, что y * 3 == x. Если x кратно 3, то y должно быть x / 3, в противном случае он должен работать через переполнение. Простой способ проверить это сравнить y с x. Также см en.wikipedia.org/wiki/Modular_multiplicative_inverse
aditsu

17

Python, 3 2 токена

Решение грубой силы, но оно работает.

0x9249249249249249249249249249249249249249249249249249249249249249>>x&1

Спасибо Говарду за сокращение на 1 токен.


Вот это да! Ваше решение, вероятно, самое короткое (3 токена), но я хочу поощрять и другие ответы.
qwr

11
Существует даже два маркера решения: 0x9......>>x&1.
Говард

6

C - 5 4 (?) Токенов

int div3_m2(uint32_t n) {
    return n == 3 * (n * 0xAAAAAAABull >> 33);
}

Работает для любого 32-разрядного числа без знака .

Этот код использует мультипликативный обратный по модулю 2 32 делителя для преобразования операции деления в операцию умножения.

редактировать

Мое решение (опубликованное через 2 минуты) имеет тот же дух, что и решение aditsu. Благодарим его за использование== которое улучшает мое решение на 1 жетон.

Ссылка


1
Это невероятно. Я знал о магических числах из известного обратного трюка с квадратным корнем, но я не знал, что его можно использовать для произвольного делителя. Это Bull: P
QWR

Да, 0xAAAAAAAB = (2 ^ 33 + 1) / 3 и 171 = (2 ^ 9 + 1) / 3. Я выбрал самую маленькую константу, которая делает трюк. Хм, на самом деле это также, кажется, работает с 86 = (2 ^ 8 + 2) / 3
aditsu

Крысы, даже 43 = (2 ^ 7 + 1) / 3 работает, не уверен, как я это пропустил. Отредактировано сейчас.
aditsu

4

C - 15 (?) Токенов

int div3_m1(unsigned int n) {
    n = (n & 0xf) + (n >> 4);
    n = (n & 0x3) + (n >> 2);
    n = (n & 0x3) + (n >> 2);
    return n == 0 || n == 3;
}

Так как 4 ≡ 1 (мод 3), мы имеем 4 n ≡ 1 (мод 3). Правило суммирования цифр не ограничивается суммированием цифр, но также позволяет нам произвольно разбивать число на последовательности цифр и суммировать их все при сохранении конгруэнтности.

Пример в базе 10, делитель = 9:

1234 ≡ 12 + 34 ≡ 1 + 2 + 3 + 4 ≡ 123 + 4 ≡ 1 (мод 9)

Все утверждения в программе используют это свойство. На самом деле его можно упростить до цикла, в котором оператор выполняется n = (n & 0x3) + (n >> 2);до тех пор n < 4, пока оператор просто разбивает число в base-4 на наименее значащую цифру и добавляет 2 части.


+1: интересно, это работает для n до 512 (фактически n = 590), но я не совсем уверен, почему.
Пол Р

@PaulR: он не будет работать для больших чисел из-за переноса (обратите внимание, что я использовал сложение в расчете). Также обратите внимание на повторяющиеся строки.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Да, я просто не уверен, почему он работает для 9-битных значений, так как он только проверяет 8-битные значения?
Paul R

для 9-битных чисел после первого добавления оно становится не более 5 бит, после первого n = (n & 0x3) + (n >> 2);результат уменьшается до 3 бит, и повторение заставляет его оставаться только 2 бита stackoverflow.com/a/3421654/995714
phuclv

1
о, я сделал ошибку 5-битное число + 4-битное число может привести к 6-битному номеру. Но если n <= 588, то при добавлении старших 4 битов и нижних 2 битов этого 6-битного числа получается только 4-битная сумма. Снова добавление, которое приводит к 2-битному числу. 589 и 590 дают 3 бита в последней сумме, но, между прочим, они не делятся на 3, поэтому результат правильный
phuclv

2

Python (2 токена?)

1&66166908135609254527754848576393090201868562666080322308261476575950359794249L>>x

Или

1&0x9249249249249249249249249249249249249249249249249249249249249249L>>x

Или

1&0b1001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001>>x

2
Дубликат комментария Говарда
aditsu

@aditsu ... Великие умы думают так же? Клянусь, я не видел этого до того, как опубликовал это.
Junıʇǝɥʇuʎs

2

JavaScript - 3 токена

function div3(n) {
    var a = n * 0.3333333333333333;
    return (a | 0) == a;
}

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


Должно быть 4 лексемы: =, *, |,==
n̴̖̋h̷͉a̷̭̿h̸̡̅ẗ̵̨d̷̰ĥ̷̳

1
Я не думаю, что присвоение переменной считается токеном.
Tyilo

1

C - 4 жетона

int div3(int x) {
    return ((x * 43) >> 7) * 3 == x;
}

Работает до 383.

Предыдущая версия (большие константы):

int div3(int x) {
    return ((x * 171) >> 9) * 3 == x;
}

Работает до 1535


1

Баш - ???

Не уверен, как это оценить.

seq 0 85 | awk '{print $1 * 3}' | grep -w [number] | wc -l

например

$ seq 0 85 | awk '{print $1 * 3}' | grep -w 11 | wc -l
0

$ seq 0 85 | awk '{print $1 * 3}' | grep -w 12 | wc -l
1

$seq 0 85 | awk '{print $1 * 3}' | grep -w 254 | wc -l
0

$seq 0 85 | awk '{print $1 * 3}' | grep -w 255 | wc -l
1

1

Befunge 93 - 5 жетонов

Исправлено - разделение удалено.

v      @._1.@
         \   
         0   
         +   
         3   
>&>3-:0\`|   
  ^      <   

Получает ввод, продолжает вычитать 3 до тех пор, пока он не станет меньше 0, направить указатель вверх ('|'), а затем добавить 3. Если значение равно 0, указатель перемещается вправо (" 1. @" выводит "1"), в противном случае перемещается влево («@. » выводит «0»). '@' завершает программу.


1

Партия - 7 жетонов

я думаю

@echo off
for /L %%a in (0,3,%1) do set a=%%a
if %a%==%1 echo 1

Возвращает, 1если данное число (как stdin) делится на три.


Разрешены ли петли?
sergiol

1

Рубин, 6 (?) Жетонов

Я действительно не знаю, как считать жетоны. ОП, ты можешь забить меня?

Я думаю , что это 6 ... 1, 0, 0, *, 255,x

Обратите внимание, что *это не целочисленное умножение.

def div3(x)
  ([1,0,0]*255)[x]
end

Разве токен в смысле ОП не будет только одним из перечисленных выше в вопросе?
C5H8NNaO4

@ C5H8NNaO4 И что? 0?
Не то, что Чарльз

@ C5H8NNaO4 может быть 4 для констант?
Не то, что Чарльз

1

Python 0

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

def g(x): return ([[lambda : g(sum(int(y) for y in list(str(x)))),lambda: 0][[False,True].index(x in[0,1,2,4,5,7,8])], lambda: 1][[False,True].index((lambda y: y in[3,6,9])(x))])()

использует трюк, что несколько из 3 имеют цифры, которые добавляют к 3

Изменить: Удалена ненужная лямбда

def g(x):return([[lambda: g(sum(int(y) for y in list(str(x)))),lambda:0][[False,True].index(x in[0,1,2,4,5,7,8])], lambda:1][[False,True].index(x in[3,6,9])])()

Изменить: Гольф дальше (117 символов) до сих пор нет жетонов

exec"g=`x:(((`:g(sum(int(y)for y in str(x)),`:0)[x in[0,1,2,4,5,7,8]],`:1)[x in[3,6,9]])()".replace('`','lambda ')

Убит прямой доступ к изящному getitem от Python Longer за 132 символа

exec"g={0}x:((({0}:g(sum(int(y)for y in str(x))),{0}:0{1}0,1,2,4,5,7,8]),{0}:1{1}3,6,9]))()".format('lambda ',').__getitem__(x in[')

http://www.codeskulptor.org/#user34_uUl7SwOBJb_0.py


Однако доступ к массиву []не разрешен.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳


Ну, вопрос не использует правило в теге вики. Вопрос имеет ограничение на разрешенные операции. Обратите внимание на слово only.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ Хорошо, у питона тоже есть нативный атрибут
Дилан Мадисетти

0

Python - 25 жетонов

Чтобы начать, у меня есть длинное решение - реализация одного из ответов в ссылке в моем первом посте. nэто вход.

a = (n>>7)-((n&64)>>6)+((n&32)>>5)-((n&16)>>4)+((n&8)>>3)-((n&4)>>2)+((n&2)>>1)-(n&1)
print(a==0 or a==3)

orэквивалентно ||.


0

JavaScript - 3 токена

Проверьте это на консоли вашего браузера:

a = prompt().split('');
sum = 0;

do {
  sum = a.reduce(function(p, c) {
     return parseInt(p) + parseInt(c); 
  });

  a = sum.toString().split('');

} while(a.length > 1)

alert([3, 6, 9].indexOf(+sum) > -1)

Как вы пришли к такому выводу? Я считаю около 37 жетонов.
nyuszika7h

«Токен - это любой из вышеперечисленных, за исключением констант и переменных». Как ты посчитал 37?
Уильям Барбоза

1
А ну понятно. ОП, кажется, не согласен с информационной страницей атомного кода-гольфа .
nyuszika7h

На самом деле, сейчас я не уверен, прав я или нет. Мой счет будет 70+ в соответствии с атомным кодом гольф-скрипки.
Уильям Барбоза

1
Проблема не в количестве токенов, а в том, какие операции вы используете. Я не думаю, что toString, parseInt, циклы, массивы и т. Д. Разрешены.
aditsu

0

JavaScript
не уверен насчет токена

function mod3 (i) { return {'undefined':'100','0':'0'}[[0][i]][i.toString (3).split('').pop ()]}

или если выход для 0 допускается равным 1;

function mod3 (i) { return '100'[i.toString (3).split('').pop ()]}


2
Я должен сказать, я не уверен, какие правила применяются к этому вызову. Разрешены ли вызовы функций и доступ к свойствам?
C5H8NNaO4

0

Tcl , 83 байта

proc T n {while \$n>9 {set n [expr [join [split $n ""] +]]};expr {$n in {0 3 6 9}}}

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


Неудачный аутгольф: 96 байт. proc T n {set n [expr [join [split [expr [join [split $n ""] +]] ""] +]];expr {$n in {0 3 6 9}}} Попробуйте онлайн!
sergiol

Еще один сбой: ** 87 байт ** proc T n {expr {[expr [join [split [expr [join [split $n ""] +]] ""] +]] in {0 3 6 9}}} Попробуйте онлайн!
sergiol
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.