Мат (или проблема с писсуаром)


35

У моего учителя в Precalc есть одна из его любимых проблем, которую он придумал (или, скорее всего, украл по мотивам xkcd ), которая связана с рядом nписсуаров. «Шах и мат» - это ситуация, в которой каждый писсуар уже занят ИЛИ рядом с ним находится занятый писсуар. Например, если человек является X, то

X-X--X

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

задача

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

Примеры

0 -> 1(отсчеты нулевой случай как мат)
1 -> 1( X)
2 -> 2( X-или -X)
3 -> 2( X-Xили -X-)
4 -> 3( X-X-, -X-Xили X--X)
5 -> 4( X-X-X, X--X-, -X-X-, или -X--X)
6 -> 5( X-X-X-, X--X-X, X-X--X, -X--X-или -X-X-X)
7 -> 7( X-X-X-X, X--X-X-, -X-X--X, -X--X-X, X-X--X-, X--X--Xили -X-X-X-)
8 -> 9( -X--X--X, -X--X-X-, -X-X--X-, -X-X-X-X, X--X--X-, X--X-X-X, X-X--X-X, X-X-X--X, X-X-X-X-)
...

счет

Победит самая маленькая программа в байтах.




12
Случай n = 0 должен быть 1. Существует ровно одна установка, которая является checkmate, и это ''. Это так же, как с факториалами и перестановками, 0! = 1, потому что есть ровно 1 способ расставить 0 предметов.
orlp


19
Никакой туалет вообще не является матовой ситуацией. : D
Тит

Ответы:


20

Оазис , 5 байт

Код

cd+2V

Расширенная версия

cd+211

объяснение

1 = a(0)
1 = a(1)
2 = a(2)

a(n) = cd+
       c      # Calculate a(n - 2)
        d     # Calculate a(n - 3)
         +    # Add them up

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


7
Это странный ответ, язык был создан около месяца назад без надлежащей документации в репо ....

2
@tuskiomi У него действительно есть документ, вinfo.txt
TuxCrafting

6
@ TùxCräftîñg уверен, если вы хотите быть техническим. Я мог бы нарисовать лошадь и назвать ее документацией к моему программному проекту. это не делает его полезным или решающим.

1
@tuskiomi info.txtполезен, он содержит документацию для каждой команды Oasis
TuxCrafting

8
@tuskiomi Это результат промедления и лени. Я постараюсь добавить краткую документацию о том, как настоящий язык работает сегодня.
Аднан

12

Java 7, 65 42 байта

int g(int u){return u>1?g(u-2)+g(u-3):1;}

Последовательность просто добавляет предыдущие элементы, чтобы получить новые. Наконечник шляпы к orlp и Пруту для этого более короткого метода;)

Старый:

int f(int u){return u<6?new int[]{1,1,2,2,3,4}[u]:f(u-1)+f(u-5);}

После пятого элемента разрыв в последовательности возрастает на пять элементов предыдущего.


Если u = 3, то ваша функция возвращает 1, но примеры показывают, что это должно быть 2.
Poke

К сожалению! Я использовал свою fфункцию из другого фрагмента вместо рекурсии. Глупый я, исправляю ...
Geobits

1
Разве эта последняя часть ( u>0?u:1;) не может стать 1;?
Конор О'Брайен

2
@Jordan Если писсуаров ноль, то «каждый писсуар уже занят» в одной возможной конфигурации. Я считаю, что контрольный пример, показанный в вопросе, неверен.
Geobits

1
Вы можете заменить u>0?u:1;)на, 1;если вы измените первое сравнение на u>1, то при u = 2 выходной будет g (0) + g (-1), что будет 2
Rod

9

Python 2, 42 40 39 35 байт

f=lambda n:n>1and f(n-2)+f(n-3)or 1

Генерация фактических наборов:

lambda n:["{:0{}b}".format(i,n).replace("0","-").replace("1","X")for i in range(2**n)if"11"not in"{:0{}b}".format(i*2,2+n).replace("000","11")]

8

Рубин, 58 34 байта

Сильно вдохновлен оригинальным ответом Geobits на Java.

f=->n{n<3?n:n<6?n-1:f[n-1]+f[n-5]}

Смотрите его на repl.it: https://repl.it/Dedh/1

Первая попытка

->n{(1...2**n).count{|i|!("%0#{n}b"%i)[/11|^00|000|00$/]}}

Смотрите его на repl.it: https://repl.it/Dedh


6

Python, 33 байта

f=lambda n:+(n<2)or f(n-2)+f(n-3)

Используются сдвинутые базовые случаи f(-1) = f(0) = f(1) = 1. Если Trueбы можно было использовать для 1, нам не нужно 3 байта для +().


6

J, 31 27 23 байта

Сохранено 4 байта благодаря милям!

0{]_&(]}.,+/@}:)1 1 2"_

Объяснение скоро придет.

Старое решение

(>.1&^)`(-&3+&$:-&2)@.(2&<)

Это повестка дня. LHS - это герунда, состоящая из двух глаголов: >.1&^и -&3+&$:-&2. Первый используется, если условие ( 2&<) не выполняется. Это означает, что форк >.1&^активируется над аргументом. Заметим:

   1 ^ 0 1 2
1 1 1
   (1&^) 0 1 2
1 1 1
   0 1 2 >. (1&^) 0 1 2
1 1 2
   (>.1&^) 0 1 2
1 1 2

Здесь >.принимает максимум два значения. Таким образом, он дает 1, 1 и 2 в качестве начальных членов.

Второй глагол в герунде - это вилка:

-&3 +&$: -&2

Левый и правый зубцы применяются к глаголу, вычитая 3 и 2 соответственно; тогда средний глагол вызывается с левыми и правыми аргументами, равными тем. $:вызывает глагол для каждого аргумента и +добавляет эти два. Это в основном эквивалентно($: arg - 3) + ($: arg - 2)

Контрольные примеры

   f =: (>.1&^)`(-&3+&$:-&2)@.(2&<)
   f 0
1
   f 2
2
   f 4
3
   f 6
5
   f 8
9
   F =: f"0         NB. for tables
   F i.13
1 1 2 2 3 4 5 7 9 12 16 21 28
   i.13
0 1 2 3 4 5 6 7 8 9 10 11 12
   (,. F) i.13
 0  1
 1  1
 2  2
 3  2
 4  3
 5  4
 6  5
 7  7
 8  9
 9 12
10 16
11 21
12 28

4

MATL , 25 23 байта

W:qB7BZ+t!XAw3BZ+!3>a>s

Попробуйте онлайн! Или проверьте все тестовые случаи .

объяснение

Две свертки! Ура!

Это создает массив, скажем, A, где каждая возможная конфигурация является строкой. 1в этом массиве представляет собой занятую позицию. Например, для ввода 4массив A

0 0 0 0
0 0 0 1
0 0 1 0
···
1 1 1 0
1 1 1 1

Затем код сворачивает массив A с [1 1 1]. Это дает массив B. Занятые позиции и соседи занятых позиций в A дают ненулевой результат в массиве B:

0 0 0 0
0 0 1 1
0 1 1 1
···
2 3 2 1
2 3 3 2

Таким образом, первое условие для того, чтобы конфигурация была матом, состоит в том, что B не содержит нулей в этой строке. Это означает, что в этом ряду A не было пустых позиций, или были некоторые, но были соседи занятых позиций.

Нам нужно второе условие. Например, последняя строка удовлетворяет вышеуказанному условию, но не является частью решения, поскольку конфигурация была недействительной с самого начала. Действительная конфигурация не может иметь две соседние занятые позиции, то есть не может иметь два смежных 1в A. Эквивалентно, она не может иметь двух смежных значений в B, превышающих 1. Таким образом, мы можем обнаружить это, сворачивая B с [1 1]и проверяя, что в результирующем массиве C,

0 0 0 0
0 1 2 1
1 2 2 1
···
5 5 3 1
5 6 5 2

никакое значение в этом ряду не превышает 3. Конечным результатом является количество конфигураций, которые удовлетворяют двум условиям.

W:q    % Range [0 1 ... n-1], where n is implicit input
B      % Convert to binary. Each number produces a row. This is array A
7B     % Push array [1 1 1] 
Z+     % 2D convolution, keeping size. Entries that are 1 or are horizontal 
       % neighbours of 1 produce a positive value. This is array B
t!     % Duplicate and transpose (rows become columns)
XA     % True for columns that contain no zeros
w      % Swap. Brings array B to top
3B     % Push array [1 1]
Z+     % 2D convolution, keeping size. Two horizontally contiguous entries
       % that exceed 1 will give a result exeeding 3. This is array C
!      % Transpose
3>     % Detect entries that exceed 3
a      % True for columns that contain at least one value that exceeds 3
>      % Element-wise greater-than comparison (logical and of first
       % condition and negated second condition)
s      % Sum (number of true values)

4

PHP 105 113 93 байта

+3 за n=1; +9 за $argv, -1-3 в гольфе
-20: заметил, что мне не нужны комбинации, а только их количество

for($i=1<<$n=$argv[1];$i--;)$r+=!preg_match("#11|(0|^)0[0,]#",sprintf("%0{$n}b,",$i));echo$r;

бежать с -r

цикл от 2 ** н-1 до 0:

  • проверить двоичный п-значное представление для 11, 000, 00в начале или в конце, или один0
  • если нет совпадения, увеличьте результат

результат печати

тот же размер, немного проще регулярное выражение

for($i=1<<$n=$argv[1];--$i;)$r+=!preg_match("#11|^00|00[,0]#",sprintf("%0{$n}b,",$i));echo$r;
  • цикл от 2 ** n-1 до 1 (вместо 0)
  • проверить двоичное представление 11, 00в начале или в конце, или000
  • ничего не печатает при n = 0

PHP, 82 байта

Арнаулд портировал и играл в гольф:

for($i=$k=1<<$n=$argv[1];--$i;)$r+=!($i&$x=$i/2|$i*2)&&(($i|$x)&~$k)==$k-1;echo$r;

ничего не печатает при n = 0


добавьте 3 байта для нового n=0: вставьте ?:1перед финалом;
Тит

4

Желе , 11 байт

,’fR_2߀So1

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

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

,’fR_2߀So1  Main link. Argument: n

 ’           Decrement; yield n - 1.
,            Pair; yield [n, n - 1].
   R         Range; yield [1, ..., n].
  f          Filter; keep the elements that are common to both lists.
             This yields [n, n - 1] if n > 1, [1] if n = 1, and [] if n < 1.
    _2       Subtract 2 from both elements, yielding [n - 2, n - 3], [-1], or [].
      ߀     Recursively call the main link for each integer in the list.
        S    Take the sum of the resulting return values.
         o1  Logical OR with 1; correct the result if n < 1.

2
Как это работает? Использует ли он рекурсивную формулу или что-то еще?
Конор О'Брайен

@ ConorO'Brien Да, он использует рекурсивную формулу. Я добавил объяснение.
Деннис

4

JavaScript (ES6) / рекурсивный, 30 27 байт

Редактировать: сохранено 3 байта благодаря Shaun H

let

f=n=>n<3?n||1:f(n-2)+f(n-3)

for(var n = 1; n < 16; n++) {
  console.log(n, f(n));
}

JavaScript (ES6) / нерекурсивный 90 77 байт

Редактировать: сохранено 13 байтов благодаря Конору О'Брайену и Титу

let f =

n=>[...Array(k=1<<n)].map((_,i)=>r+=!(i&(x=i>>1|i+i))&&((i|x)&~k)==k-1,r=0)|r

for(var n = 1; n < 16; n++) {
  console.log(n, f(n));
}


1
Я думаю, что ((i|r|l)&(k-1))может стать ((i|r|l)&k-1), или даже((i|r|l)&~-k)
Конор О'Брайен

один байт: i<<1-> i*2илиi+i
Тит

1
Вы можете использовать одну переменную для л и г, экономия 6 байт: !(i&(x=i>>1|i+i))&&((i|x)&(k-1))==k-1; и если вы можете вставить ,k--куда - нибудь, вы можете заменить k-1с , kчтобы сохранить круглые скобки.
Тит

&(k-1)в любом случае не нуждается в паренсе; но вы можете использовать &~kвместо этого.
Тит

1
Я просто собираюсь оставить это здесь:f=n=>n<3?n||1:f(n-2)+f(n-3)
Шон Х

3

Mathematica, 35 байт

a@0=a@1=1;a@2=2;a@b_:=a[b-2]+a[b-3]

Определяет функцию a. Принимает целое число в качестве входных данных и возвращает целое число в качестве выходных данных. Простое рекурсивное решение.


3

AnyDice , 51 байт

function:A{ifA<3{result:(A+2)/2}result:[A-2]+[A-3]}

Здесь должно быть больше ответов AnyDice.

Мое решение определяет рекурсивную функцию, которая вычисляет a(n)=a(n-2)+a(n-3). Он возвращает a(0)=a(1)=1и a(2)=2использует некоторую магию целочисленного деления.

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

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


3

Perl, 35 34 байта

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

Внести вклад в STDIN

checkmate.pl <<< 8

checkmate.pl:

#!/usr/bin/perl -p
$\+=$b-=$.-=$\-$b*4for(++$\)x$_}{

Недавно разработанная секретная формула. Ripple обновляет 3 переменные состояния без необходимости параллельных присваиваний.

Это одинаково мало (но намного медленнее и занимает намного больше памяти), чтобы просто решить исходную проблему:

#!/usr/bin/perl -p
$_=grep!/XX|\B-\B/,glob"{X,-}"x$_

но это не работает для 0


2

JavaScript (ES6), 62 байта

n=>[1,...Array(n)].reduce(($,_,i,a)=>a[i]=i<3?i:a[i-3]+a[i-2])

Это первый раз, когда мне понадобились два фиктивных имен переменных. Рекурсивная версия, вероятно, будет короче, но мне действительно нравится reduce... Редактировать: Нашел решение, также 62 байта, которое имеет только одну фиктивную переменную:

n=>[1,...Array(n)].reduce((p,_,i,a)=>a[i]=i<5?i+2>>1:a[i-5]+p)

2

Желе , 19 байт

Рекурсивное решение , вероятно, короче ...

Ḥ⁹_c@⁸
+3µ:2R0;瀵S

Смотрите это на TryItOnline
или смотрите серию для n = [0, 99], также на TryItOnline

Как?

Возвращает n+3номер Падована путем подсчета комбинаций

Ḥ⁹_c@⁸ - Link 1, binomial(k, n-2k): k, n
Ḥ      - double(2k)
 ⁹     - right argument (n)
  _    - subtract (n-2k)
     ⁸ - left argument (k)
   c@  - binomial with reversed operands (binomial(k, n-2k))

+3µ:2R0;瀵S - Main link: n
  µ       µ  - monadic chain separation
+3           - add 3 (n+3)
   :2        - integer divide by 2 ((n+3)//2)
     R       - range ([1,2,...,(n+3)//2]
      0;     - 0 concatenated with ([0,1,2,...,(n+3)//2]) - our ks
        ç€   - call previous link as a dyad for each
           S - sum

2

> <> , 25 + 2 = 27 байт

211rv
v!?:<r@+@:$r-1
>rn;

Требуется, чтобы входные данные присутствовали в стеке при запуске программы, поэтому +2 байта для -vфлага. Попробуйте онлайн!

Первая строка инициализирует стек 1 1 2 n, где nнаходится входной номер. Вторая строка, идущая в обратном порядке, проверяет, что nбольше 1. Если это так, nуменьшается, и следующий элемент в последовательности генерируется следующим образом:

r$:@+@r              a(n-3) a(n-2) a(n-1) n

r        Reverse   - n a(n-1) a(n-2) a(n-3)
 $       Swap      - n a(n-1) a(n-3) a(n-2)
  :      Duplicate - n a(n-1) a(n-3) a(n-2) a(n-2)
   @     Rotate 3  - n a(n-1) a(n-2) a(n-3) a(n-2)
    +    Add       - n a(n-1) a(n-2) a(n)
     @   Rotate 3  - n a(n) a(n-1) a(n-2)
      r  Reverse   - a(n-2) a(n-1) a(n) n

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


2

CJam , 20 байтов

1_2_{2$2$+}ri*;;;o];

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

объяснение

При этом используются отношения повторения, показанные на странице OEIS .

1_2_                   e# Push 1, 1, 2, 2 as initial values of the sequence
           ri          e# Read input
    {     }  *         e# Repeat block that many times
     2$2$              e# Copy the second and third elements from the top
         +             e# Add them
              ;;;      e# Discard the last three elements
                 o     e# Output
                  ];   e# Discard the rest to avoid implicit display

2

05AB1E , 12 байтов

XXXIGX@DŠ0@+

объяснение

XXX            # initialize stack as 1, 1, 1
   IG          # input-1 times do:
     X@        # get the item 2nd from bottom of the stack
       DŠ      # duplicate and push one copy down as 2nd item from bottom of the stack
         0@    # get the bottom item from the stack
           +   # add the top 2 items of the stack (previously bottom and 2nd from bottom)
               # implicitly print the top element of the stack after the loop

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


1

FRACTRAN, 104 93 байта

Вход есть, 11**n*29а выход есть 29**checkmate(n).

Это в основном для развлечения, тем более что в настоящее время меня обгоняют Python, JS и Java. Тем не менее, такое же количество байтов, как в PHP: D Предложения по игре в гольф приветствуются.

403/85 5/31 3/5 9061/87 3/41 37/3 667/74 37/23 7/37 38/91 7/19 5/77 1/7 1/17 1/2 340/121 1/11

Ungolfing

               At the start we have 11**n * 29
1/11           If n < 2, we remove the 11s and print 29**1
340/121        If n >= 2, we subtract two 11s (n-2) and add one 17, two 2s and one 5.
                 We now have 17**1 * 29**1 * 2**2 * 5.
                 These are the register for a, b, c at registers 17, 29, and 2.
                 5 is an indicator to start the first loop.
                 This loop will move a to register 13.
403/85 5/31    Remove the 17s one at a time, adds them to the 13 register.
                 5 and 31 reset the loop.
3/5            Next loop: moves b to a and adds b to a in register 13.
9061/87 3/41   Remove the 29s one at a time, adds them to the 17 and 13 registers.
                 3 and 41 reset the loop.
37/3           Next loop: moves c to b in register 29.
667/74 37/23   Remove the 2s one at a time, adds them to the 29 register.
                 37 and 23 reset the loop.
7/37           Next loop: moves a+b to c in register 2.
38/91 7/19     Remove the 13s one at a time, adds them to the 2 register.
                 7 and 19 reset the loop.
5/77           Move to the first loop if and only if we have an 11 remaining.
1/7 1/17 1/2   Remove the 7 loop indicator, and all 17s and 2s.
               Return 29**checkmate(n).

1

На самом деле, 25 байтов

Это кажется немного длинным для простого f(n) = f(n-2) + f(n-3)отношения повторения. Предложения по игре в гольф приветствуются. Попробуйте онлайн!

╗211╜¬`);(+)`nak╜2╜2<I@E

Ungolfing

         Implicit input n.
╗        Save n to register 0.
211      Stack: 1, 1, 2. Call them a, b, c.
╜¬       Push n-2.
`...`n   Run the following function n-2 times.
  );       Rotate b to TOS and duplicate.
  (+       Rotate a to TOS and add to b.
  )        Rotate a+b to BOS. Stack: b, c, a+b
         End function.
ak       Invert the resulting stack and wrap it in a list. Stack: [b, c, a+b]
╜        Push n.
2        Push 2.
╜2<      Push 2 < n.
I        If 2<n, then 2, else n.
@E       Grab the (2 or n)th index of the stack list.
         Implicit return.

1

На самом деле , 18 байт

Это на самом деле более длинный ответ Дениса на желе. Предложения по игре в гольф приветствуются. Попробуйте онлайн!

3+;╖½Lur⌠;τ╜-@█⌡MΣ

Ungolfing

         Implicit input n.
3+       Add 3. For readibility, m = n+3.
;╖       Duplicate and store one copy of m in register 0.
½Lu      floor(m/2) + 1.
r        Range from 0 to (floor(m/2)+1), inclusive.
⌠...⌡M   Map the following function over the range. Variable k.
  ;        Duplicate k.
  τ╜-      Push m-2k. Stack: [m-2k, k]
  @█       Swap k and m-2k and take binomial (k, m-2k).
            If m-2k > k, █ returns 0, which does not affect the sum() that follows.
         End function.
Σ        Sum the list that results from the map.
         Implicit return.



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