Desafio
Origami (papel dobrável) é uma forma criativa de arte. Tanto quanto eu sei, o mestre de Origami prefere papel quadrado. Vamos começar do começo - converta um papel retangular em um quadrado.
Então o papel é dividido em quadrados. Removemos o maior quadrado que compartilha uma aresta mais curta com a forma atual, passo a passo (veja a figura abaixo). E se a parte restante após uma etapa for menor ou igual a 0.001 * (area of the original paper)
, o papel não poderá mais ser dividido. É possível que nada permaneça finalmente.
Sua tarefa é calcular quantos quadrados são feitos durante o processo. O quadrado da última etapa que impossibilita a divisão do papel é contado na saída.
Exemplo (um papel de 1.350
largura / altura), a saída é 10:
Entrada e saída
Entrada: proporção largura / altura do papel retangular, um decimal (ou um número inteiro sem o ponto) de 1.002
para 1.999
com uma etapa mínima de 0.001
. Você também pode usar qualquer outro formato razoável que descreva a proporção. Apenas mencione isso na sua resposta.
Saída: contagem quadrada, um número inteiro.
Exemplo de E / S
Um formato de mapeamento é usado para manter a página organizada, enquanto seu código não precisa suportar uma entrada de lista nem ser uma função de mapeamento.
1.002 => 251
1.003 => 223
1.004 => 189
1.005 => 161
1.006 => 140
1.007 => 124
1.008 => 111
1.009 => 100
Graças a @LuisMendo, aqui está o gráfico de respostas.
Observações
- Este é um código de golfe, então o código mais curto ganha
- Preste atenção às brechas padrão
- É sua liberdade decidir como lidar com entradas e saídas, mas elas devem seguir as restrições padrão.
A propósito...
- Comente se você tem alguma dúvida sobre o desafio
- Pessoalmente, sugiro que sua resposta contenha uma explicação se você estiver usando um idioma de golfe
- Graças a @GregMartin, leia sua resposta para obter uma boa explicação matemática para o desafio.
Código de exemplo
Aqui está uma versão simplificada do código C ++:
#include <iostream>
#include <utility>
int f (double m)
{
double n = 1, k = 0.001;
int cnt = 0;
k *= m; // the target minimum size
while(m*n >= k)
{
m -= n; // extract a square
if(n > m)
std::swap(n, m); // keep m > n
++ cnt;
}
return cnt;
}
int main()
{
double p;
std::cin >> p;
std::cout << f(p);
return 0;
}
Todos os cálculos relacionados no código de exemplo precisam de uma precisão de 6 dígitos decimais, abrangidos float
.
Respostas:
MATL , 19 bytes
A entrada é uma matriz com os dois números que definem a proporção original, como
[1, 1.009]
. (Não é necessário que os números sejam classificados ou que um deles seja 1.)Experimente online!
Explicação
fonte
Haskell ,
71 70 65 63 62 61 5856 bytesObrigado a @xnor por algumas melhorias engenhosas!
Experimente online!
fonte
m==n
final pode ser1>0
porque é a única possibilidade restante. Ou talvez os casos possam ser reorganizados para permitir uma ligação aqui.n>m
for expandido paran>=m
e a primeira verificação for gravadae>m*n*1000
, isso deve dar1
igualdade.(n#m)e|e>n*m*1e3=0|n<m=m#n$e|d<-n-m=(d#m)e+1;n!m=n#m$n*m
d<-n-m
comootherwise
é realmente legal !!!JavaScript (ES6),
5958 bytesTeste
Mostrar snippet de código
fonte
Mathematica, não concorrente (21 bytes)
Esta resposta não é competitiva porque não responde à pergunta real! Mas ele responde a uma variante da pergunta e fornece uma desculpa para destacar algumas matemáticas interessantes.
Função simbólica, tendo como entrada um número racional positivo (cujo numerador e denominador representam as dimensões do artigo original) e retornando um número inteiro positivo. Por exemplo,
Tr@*ContinuedFraction[1350/1000]
retorna10
. (ContinuedFraction
atua de maneira diferente nos números de ponto flutuante devido a problemas de precisão, e é por isso que um número racional é necessário como entrada nesse contexto.)Uma interpretação interessante do procedimento geométrico descrito no problema (cortar quadrados um retângulo repetidamente) é que é uma implementação do algoritmo euclidiano para encontrar os maiores divisores comuns! Considere o exemplo da pergunta em si, com relação
1.35
, que pode ser modelado com um pedaço de papel com dimensões (1350,1000). Toda vez que um quadrado é cortado, o número menor é subtraído do número maior; portanto, os retângulos resultantes neste exemplo têm dimensões (350.1000), depois (350.650), depois (350.300), depois (50.300), depois (50.250) e (50.200) e (50.150) e (50.100) e (50.100) 50), e também (50,0) uma vez que tiramos o último quadrado de si mesmo. É exatamente assim que o algoritmo euclidiano opera (módulo a diferença entre divisão e subtração repetida) e, de fato, vemos que 50 é realmente o MDC de 1350 e 1000.Tipicamente, no algoritmo euclidiano, é possível acompanhar essas dimensões intermediárias e descartar o número de subtrações; no entanto, é possível registrar alternadamente quantas vezes subtraímos um número do outro antes que a diferença se torne muito pequena e precisamos mudar o que estamos subtraindo. Esse método de gravação é precisamente a fração continuada de um número racional. (Frações contínuas de números irracionais, que nunca terminam, também são super legais, mas não relevantes aqui.) Por exemplo, no exemplo 1350/1000, subtraímos 1000
1
vezes, depois 3502
vezes, depois 3001
, depois 506
vezes; portanto, a fração continuada de 1350/1000 é{1,2,1,6}
. Matematicamente, reescrevemos 1350/1000 como1
+ 1 / (2
+ 1 / (1
+ 1 /6
)), que você pode verificar.Portanto, para esse problema, se você não parar quando os quadrados ficarem menores que um determinado limiar, mas simplesmente contar todos os quadrados finitos antes que ele pare, o número total de quadrados será igual ao número total de subtrações, ou seja a soma de todos os números inteiros na fração continuada - e é exatamente isso que a composição das funções
Tr@*ContinuedFraction
calcula! (No exemplo 1.35, ele obtém a resposta que o OP deseja, porque o quadrado final é grande o suficiente para que todos os quadrados fossem contados. MasTr@*ContinuedFraction[1001/1000]
, por exemplo, cede1001
, uma vez que conta o único quadrado enorme e todos os 1000 dos pequenos quadrados 1x1000 .)fonte
Mathematica,
6453 bytesUma solução imperativa (estilo C) tem exatamente o mesmo comprimento:
fonte
C (GCC / Clang),
6159 bytesA entrada é dois números inteiros (largura e altura) sem ponto, como
f(1999,1000)
.Espero que alguém possa salvar um byte pressionando C no clube de 58 bytes. ;)
fonte
m-=n
C, 59 bytes
Experimente online
A entrada é um número inteiro, que é a relação largura / altura em milésimos (por exemplo, 1002 para 1,002: 1).
Versão ungolfed
fonte