Xeque-mate (também conhecido como problema do mictório)

35

Meu professor do Precalc tem um dos seus problemas favoritos que ele inventou (ou mais provavelmente roubou inspirado no xkcd ) que envolve uma fileira de nmictórios. "Xeque-mate" é uma situação em que todo mictório já está ocupado OU possui um mictório próximo a eles. Por exemplo, se uma pessoa é uma X, então

X-X--X

é considerado xeque-mate. Observe que uma pessoa não pode ocupar um urinol próximo a um urinol já ocupado.

Tarefa

Seu programa analisará um número stdin, argumentos de linha de comando ou um argumento de função. Seu programa imprimirá ou retornará o número de maneiras pelas quais o xeque-mate pode ocorrer com o número digitado de mictórios.

Exemplos

0 -> 1(as contagens de casos nula como checkmate)
1 -> 1( X)
2 -> 2( X-ou -X)
3 -> 2( X-Xou -X-)
4 -> 3( X-X-, -X-X, ou X--X)
5 -> 4( X-X-X, X--X-, -X-X-, ou -X--X)
6 -> 5( X-X-X-, X--X-X, X-X--X, -X--X-ou -X-X-X)
7 -> 7( X-X-X-X, X--X-X-, -X-X--X, -X--X-X, X-X--X-, X--X--Xou -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-)
...

Pontuação

O menor programa em bytes vence.

AMACB
fonte
3
Relacionado .
betseg 21/09/16
3
Relacionados
mbomb007
12
O caso n = 0 deve ser 1. Existe exatamente uma configuração que é checkmate, e é isso ''. É o mesmo que com fatorial e permutações, 0! = 1, porque existe exatamente uma maneira de organizar 0 itens.
orlp 21/09/16
12
oeis.org/A228361
DJMcMayhem
19
Nenhum banheiro é realmente uma situação de xeque-mate. : D
Titus

Respostas:

20

Oásis , 5 bytes

Código

cd+2V

Versão extendida

cd+211

Explicação

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

Experimente online!

Adnan
fonte
7
Esta é uma resposta estranha, a linguagem foi criada cerca de um mês sem a devida documentação no repo ....
2
@tuskiomi Ele tem um documento, eminfo.txt
TuxCrafting
6
@ TùxCräftîñg certeza, se você quer ser técnico. Eu poderia desenhar um cavalo e chamá-lo de documentação para o meu projeto de programação. isso não a torna útil ou decisiva.
11
@tuskiomi info.txté útil, ele contém uma documentação para cada comandos Oasis
TuxCrafting
8
@tuskiomi Esse é o resultado da procrastinação e preguiça. Vou tentar adicionar uma documentação concisa sobre como o idioma atual funciona hoje.
Adnan
12

Java 7, 65 42 bytes

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

A sequência apenas adiciona elementos anteriores para obter novos. Gorjeta de chapéu para orlp e Rod para esse método mais curto;)

Velho:

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

Após o quinto elemento, a lacuna na sequência aumenta pelo elemento cinco anterior.

Geobits
fonte
Se u = 3 então a sua função retorna 1, mas os exemplos mostram que ele deve ser 2.
puxão
Opa! Eu estava usando minha ffunção do outro trecho em vez de recorrência. Me estúpido, fixação ...
Geobits
11
Essa última parte ( u>0?u:1;) não pode se tornar 1;?
Conor O'Brien
2
@ Jordânia Se não houver mictórios, então "todos os mictórios já estão ocupados" na única configuração possível. Eu acredito que o caso de teste mostrado na pergunta está errado.
Geobits
11
Você pode substituir u>0?u:1;)por 1;se alterar a primeira comparação para u>1, então em u = 2 a saída será g (0) + g (-1), que será 2
Rod
9

Python 2, 42 40 39 35 bytes

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

Gerando os conjuntos reais:

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")]
orlp
fonte
8

Ruby, 58 34 bytes

Fortemente inspirado pela resposta Java original dos Geobits.

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

Veja em repl.it: https://repl.it/Dedh/1

Primeira tentativa

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

Veja em repl.it: https://repl.it/Dedh

Jordânia
fonte
6

Python, 33 bytes

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

Usa os casos base deslocados f(-1) = f(0) = f(1) = 1. Se Truepudesse ser usado para 1, não precisaríamos de 3 bytes para o +().

xnor
fonte
6

J, 31 27 23 bytes

Economizou 4 bytes graças a milhas!

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

Uma explicação está para vir em breve.

Solução antiga

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

Esta é uma agenda. O LHS é um gerúndio composto por dois verbos: >.1&^e -&3+&$:-&2. O primeiro é usado se a condição ( 2&<) falhar. Isso significa que o fork >.1&^é ativado sobre o argumento. Observar:

   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

Aqui, >. leva o máximo de dois valores. Assim, produz 1, 1 e 2 como os termos iniciais.

O segundo verbo no gerúndio é um garfo:

-&3 +&$: -&2

Os dentes esquerdo e direito são aplicados ao verbo, subtraindo 3 e 2 respectivamente; então o verbo do meio é chamado com argumentos esquerdo e direito iguais a esses. $:chama o verbo em cada argumento e+ adiciona esses dois. É basicamente equivalente a($: arg - 3) + ($: arg - 2)

Casos de teste

   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
Conor O'Brien
fonte
4

MATL , 25 23 bytes

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

Experimente online! Ou verifique todos os casos de teste .

Explicação

Duas convoluções! Yay!

Isso cria uma matriz, digamos A, onde cada configuração possível é uma linha. 1nesta matriz representa uma posição ocupada. Por exemplo, para entrada, 4a matriz A é

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

O código convolve a matriz A com [1 1 1]. Isso fornece uma matriz B. As posições ocupadas e os vizinhos das posições ocupadas em A fornecem um resultado diferente de zero na matriz B:

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

Portanto, a primeira condição para uma configuração ser um xeque-mate é que B não contém zeros nessa linha. Isso significa que naquela fila de A não havia posições vazias, ou havia algumas que eram vizinhas de posições ocupadas.

Precisamos de uma segunda condição. Por exemplo, a última linha atende à condição acima, mas não faz parte da solução porque a configuração não era válida para começar. Uma configuração válida não pode ter duas posições ocupadas vizinhas, ou seja, não pode ter duas contíguas 1em A. Equivalentemente, não pode ter dois valores contíguos em B excedendo 1. Assim, podemos detectar isso convolvendo B com [1 1]e verificando que, na matriz resultante, C,

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

nenhum valor nessa linha excede 3. O resultado final é o número de configurações que atendem às duas condições.

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)
Luis Mendo
fonte
4

PHP, 105 113 93 bytes

+3 para n=1; +9 para $argv, -1-3 jogou
-20: notei que não tenho as combinações, mas apenas a contagem

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

correr com -r

loop de 2 ** n-1 a 0:

  • verificar representação binária n dígitos para 11, 000,00 no início ou no final, ou uma única0
  • se não houver correspondência, aumente o resultado

resultado de impressão

mesmo tamanho, regex um pouco mais simples

for($i=1<<$n=$argv[1];--$i;)$r+=!preg_match("#11|^00|00[,0]#",sprintf("%0{$n}b,",$i));echo$r;
  • loop de 2 ** n-1 a 1 (em vez de 0)
  • verifique a representação binária para 11,00 no início ou no final, ou000
  • imprime nada para n = 0

PHP, 82 bytes

A resposta de Arnauld portou e jogou golfe :

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

imprime nada para n = 0

Titus
fonte
adicione 3 bytes para o novo n=0: insira ?:1antes da final;
Titus
4

Gelatina , 11 bytes

,’fR_2߀So1

Experimente online! ou verifique todos os casos de teste .

Como funciona

,’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.
Dennis
fonte
2
Como é que isso funciona? Ele usa a fórmula recursiva ou outra coisa?
Conor O'Brien
@ ConorO'Brien Sim, ele usa a fórmula recursiva. Eu adicionei uma explicação.
Dennis
4

JavaScript (ES6) / Recursivo, 30 27 bytes

Edit: salvou 3 bytes graças a 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) / Não recursivo 90 77 bytes

Edit: salvou 13 bytes graças a Conor O'Brien e Titus

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));
}

Arnauld
fonte
11
Eu acho que ((i|r|l)&(k-1))pode se tornar ((i|r|l)&k-1), ou mesmo((i|r|l)&~-k)
Conor O'Brien
um byte: i<<1-> i*2oui+i
Titus
11
É possível utilizar uma variável de L e R, poupando 6 bytes: !(i&(x=i>>1|i+i))&&((i|x)&(k-1))==k-1; e se você pode inserir em ,k--algum lugar, pode substituir k-1por kpara salvar parênteses.
Titus
&(k-1)não precisa de parênteses de qualquer maneira; mas você pode usar &~k.
Titus
11
eu só vou deixar isso aqui:f=n=>n<3?n||1:f(n-2)+f(n-3)
Shaun H
3

Mathematica, 35 bytes

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

Define uma função a. Pega um número inteiro como entrada e retorna um número inteiro como saída. Solução recursiva simples.

LegionMammal978
fonte
3

AnyDice , 51 bytes

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

Deve haver mais respostas do AnyDice por aqui.

Minha solução define uma função recursiva que calcula a(n)=a(n-2)+a(n-3). Ele retorna a(0)=a(1)=1e a(2)=2usa alguma mágica de divisão inteira.

Experimente online

Nota: a saída pode parecer estranha, e é porque geralmente é usada para gerar probabilidades de dados. Basta olhar para o número à esquerda do gráfico de barras.

DanTheMan
fonte
3

Perl, 35 34 bytes

Inclui +1 para -p

Dê entrada no STDIN

checkmate.pl <<< 8

checkmate.pl:

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

Uma fórmula secreta recém-desenvolvida. O Ripple atualiza 3 variáveis ​​de estado sem a necessidade de atribuições paralelas.

É igualmente curto (mas muito mais lento e consome muito mais memória) resolver apenas o problema original:

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

mas isso não funciona para 0

Ton Hospel
fonte
2

JavaScript (ES6), 62 bytes

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

É a primeira vez que preciso de dois nomes de variáveis ​​fictícios. Uma versão recursiva provavelmente seria mais curta, mas eu realmente gosto reduce... Edit: Encontrei uma solução, também com 62 bytes, que possui apenas uma variável dummy:

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

Geléia , 19 bytes

A solução recursiva é provavelmente mais curta ...

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

Veja no TryItOnline
Ou veja a série n = [0, 99], também no TryItOnline

Quão?

Retorna o n+3número do th Padovan contando combinações

Ḥ⁹_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
Jonathan Allan
fonte
2

> <> , 25 + 2 = 27 bytes

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

Precisa que a entrada esteja presente na pilha no início do programa, portanto, +2 bytes para o -vsinalizador. Experimente online!

A primeira linha inicializa a pilha para 1 1 2 n, onde nestá o número de entrada. A segunda linha, executando para trás, verifica que né maior que 1. Se for, né decrementada e o próximo elemento na sequência é gerado da seguinte maneira:

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

A linha final gera o número na parte inferior da pilha, que é o elemento necessário na sequência.

Sok
fonte
2

CJam , 20 bytes

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

Experimente online!

Explicação

Isso usa o relacionamento de recorrência mostrado na página 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
Luis Mendo
fonte
2

05AB1E , 12 bytes

XXXIGX@DŠ0@+

Explicação

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

Experimente online!

Emigna
fonte
1

FRACTRAN, 104 93 bytes

Entrada é 11**n*29e saída é 29**checkmate(n).

Isso é divertido, principalmente porque atualmente estou sendo derrotado por Python, JS e Java. Mesmo número de bytes que o PHP: D Sugestões de golfe são bem-vindas.

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).
Sherlock9
fonte
1

Na verdade, 25 bytes

Isso parece um pouco longo para uma simples f(n) = f(n-2) + f(n-3)relação de recorrência. Sugestões de golfe são bem-vindas. Experimente online!

╗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.
Sherlock9
fonte
1

Na realidade , 18 bytes

Este é realmente um exemplo da resposta mais longa de Dennis para Jelly. Sugestões de golfe são bem-vindas. Experimente online!

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.
Sherlock9
fonte
0

Stax , 7 bytes

ÉKΦΘÄO¢

Execute e depure

Usa a relação de recorrência. C(n) = C(n-2) + C(n-3)

recursivo
fonte