Você ensina uma classe de alunos com preferências interessantes sobre como as cadeiras são organizadas. Existem três requisitos muito específicos para a organização das cadeiras:
A maioria deles é organizada em um retângulo, mesmo que isso signifique que algumas cadeiras ficam vazias.
Deve haver o mínimo de cadeiras vazias possível.
Eles devem ser o mais "quadrado" possível. A quadratura é determinada pela distância entre a largura e a altura do retângulo, quanto menor, melhor. Por exemplo, um retângulo
4x7
com um quadrado de 3.
Para ser mais específico, a "pontuação" de um arranjo é a distância entre a largura e a altura, mais o número de cadeiras que ficariam vazias.
Vamos dar um exemplo. Digamos que você tenha 13 alunos. Você pode organizar as cadeiras de qualquer uma das seguintes maneiras:
1x13
2x7
3x5
4x4
1x13
não é muito quadrado. De fato, 1 e 13 são 12 separados, então damos a esse arranjo 12 pontos. Ele também tem 0 cadeiras vazias, então adicionamos 0 pontos, dando a esse arranjo uma pontuação de 12. Não é tão bom assim.
2x7
é certamente melhor. 2 e 7 são separados apenas por 5, por isso damos 5 pontos a esse arranjo. No entanto, se você realmente organizasse duas fileiras de sete cadeiras, seriam 14 cadeiras, o que significa que uma cadeira estaria vazia. Então, adicionamos um ponto, atribuindo a esse arranjo uma pontuação de 6.
Nós também poderíamos fazer 3x5
. 3 e 5 são 2 separados, então +2 pontos. São necessárias 15 cadeiras, o que significa que teríamos duas cadeiras extras, mais outros 2 pontos, para uma pontuação de 4.
Última opção 4x4
. 4 e 4 são 0 separados, portanto, atribuímos +0 pontos. O 4x4 ocupa 16 cadeiras, portanto, 3 cadeiras ficam vazias, obtendo uma pontuação total de 3. Essa é a solução ideal.
Em caso de empate, a solução ideal é aquela com menos cadeiras vazias.
O desafio
Você deve escrever um programa ou função que use um número inteiro e produza o arranjo ideal de cadeiras para esse número de alunos. O IO pode estar em qualquer formato razoável. Aqui está um exemplo de saída para qualquer número de alunos de 1 a 100:
1: (1, 1)
2: (1, 2)
3: (2, 2)
4: (2, 2)
5: (2, 3)
6: (2, 3)
7: (3, 3)
8: (3, 3)
9: (3, 3)
10: (2, 5)
11: (3, 4)
12: (3, 4)
13: (4, 4)
14: (4, 4)
15: (4, 4)
16: (4, 4)
17: (3, 6)
18: (3, 6)
19: (4, 5)
20: (4, 5)
21: (3, 7)
22: (5, 5)
23: (5, 5)
24: (5, 5)
25: (5, 5)
26: (4, 7)
27: (4, 7)
28: (4, 7)
29: (5, 6)
30: (5, 6)
31: (4, 8)
32: (4, 8)
33: (6, 6)
34: (6, 6)
35: (6, 6)
36: (6, 6)
37: (5, 8)
38: (5, 8)
39: (5, 8)
40: (5, 8)
41: (6, 7)
42: (6, 7)
43: (5, 9)
44: (5, 9)
45: (5, 9)
46: (7, 7)
47: (7, 7)
48: (7, 7)
49: (7, 7)
50: (5, 10)
51: (6, 9)
52: (6, 9)
53: (6, 9)
54: (6, 9)
55: (7, 8)
56: (7, 8)
57: (6, 10)
58: (6, 10)
59: (6, 10)
60: (6, 10)
61: (8, 8)
62: (8, 8)
63: (8, 8)
64: (8, 8)
65: (6, 11)
66: (6, 11)
67: (7, 10)
68: (7, 10)
69: (7, 10)
70: (7, 10)
71: (8, 9)
72: (8, 9)
73: (7, 11)
74: (7, 11)
75: (7, 11)
76: (7, 11)
77: (7, 11)
78: (9, 9)
79: (9, 9)
80: (9, 9)
81: (9, 9)
82: (7, 12)
83: (7, 12)
84: (7, 12)
85: (8, 11)
86: (8, 11)
87: (8, 11)
88: (8, 11)
89: (9, 10)
90: (9, 10)
91: (7, 13)
92: (8, 12)
93: (8, 12)
94: (8, 12)
95: (8, 12)
96: (8, 12)
97: (10, 10)
98: (10, 10)
99: (10, 10)
100: (10, 10)
Como de costume, isso é código-golfe, então as brechas padrão se aplicam e o vencedor é a resposta mais curta em bytes.
Respostas:
Geléia ,
161514 bytesExperimente online! ou verifique todos os casos de teste .
Como funciona
fonte
Python 2, 68 bytes
Equivalente ao mais "óbvio":
fonte
range(-n,0)
, como eu faço na minha resposta . Suíte de teste.Haskell, 65 bytes
Exemplo de uso:
map f [1..5]
->[(1,1),(1,2),(2,2),(2,2),(2,3)]
.Passa por um loop externo
a
de1
atéx
(x -> número de alunos) e um loop internob
de1
atéa
. Mantém tudo(b,a)
ondea*b>=x
e constrói pares dos((arrangement points,seats left), (b,a))
quais seguem a ordem lexicográfica de que precisamos para encontrar o mínimo. Nota:a
é sempre maior queb
, portanto, não precisamosabs
de quadratura. Não há necessidade de subtrairx
da pontuação "assentos restantes", porque apenas a ordem relativa é importante. Finalmente, removemos o par de pontos comsnd
.fonte
a*b
(número de assentos grátis) é o desempate se a pontuação principal for igual. Por exemplon=43
: a)a=7, b=7
, pontuação:(49,49)
b)a=9, b=5
, pontuação:(49,45)
. A pontuação principal é igual, o desempate decide, b) vence.a*b
, os próprios números(b,a)
que eu tenho que carregar de qualquer maneira atuam como desempate e dão os mesmos resultados para (pelo menos)n=1..300
. Um produto é pequeno se um dos fatores (aquib
) for pequeno. Mas enquanto eu não tiver uma prova formal, não quero usar esse fato. Vamos ver se encontro um.Ruby, 64 bytes
Uma lambada que toma o número de pessoas como argumento e retorna uma matriz com largura e altura da solução ideal.
fonte
w*h
como o segundo elemento em sua matriz? Não acho que isso mude particularmente quando você liga,min
porque minimiza a pontuação, também conhecida como o primeiro elemento.In case of a tie, the optimal solution is the one with less empty chairs
MATL , 18 bytes
Experimente online!
Explicação
fonte
Javascript, 98 bytes
Meu primeiro código de golfe, então eu posto de qualquer maneira!
Inicialmente, meu
o
objeto era vazio e eu verifiquei seo.a
estava vazio, por isso foi um caso especial na primeira rodada. Mas eu encontrei o truque 1/0 na resposta do edc65 para inicializar a variável para o Infinito.fonte
Pitão,
242221 bytesEdit : na chave de classificação, percebo que não há necessidade de encontrar o número de cadeiras vazias. É equivalente a marcar o número total de cadeiras. Isso me salvou 2 bytes.
Experimente online!
fonte
Matlab
(174) (146)121truque 1: adicionei a quantia
1-1/length*width
como pontuaçãotruque 2: calculei o
number_students/length
teto para a largura do retângulo,o limite superior é o quadrado, mas também o tetoTenho certeza de que pode ser jogado ainda mais ...
tente
Edit: referenciado aos comentários de @StewieGriffin.
Edição 2:
1
en
são constantes, não é necessário adicioná-las à pontuação geral.Edit 3: teste de desempenho.
fonte
unique
Python 2, 64 bytes
Esta é uma amálgama da resposta Python do @ Lynn (de onde fiz o
max(...)[1:]
truque) e do algoritmo da minha resposta Julia (que permite uma implementação um pouco mais curta).Teste em Ideone .
fonte
Julia,
6159555352 bytesExperimente online!
Como funciona
O código é equivalente à seguinte versão não destruída, onde
cld
é a divisão do teto.Para encontrar o arranjo ideal, é claramente suficiente examinar os pares [i, j] , onde 1 ≤ i ≤ n e j = ⌈n / i⌉ .
A pontuação para esse arranjo é | j - i | + (ij - n) , onde o segundo somatório é o número de cadeiras vazias. Em vez das pontuações reais, podemos comparar pontuações aumentadas por uma constante, como ij + | j - i | + 1 .
É suficiente considerar os pares [i, j] onde i ≤ j, pois os arranjos [i, j] e [j, i] são igualmente válidos. Lidamos com pares estritamente decrescentes definindo j = max (⌈n / i⌉, i) , o que garante que j ≥ ie produza uma pontuação abaixo do ideal se /n / i⌉ <i .
Como j - i ≥ 0 , temos ij + | j - i | + 1 = ij + j - i + 1 = (i + 1) × (j - 1) , que pode ser calculado em menos bytes de código.
Finalmente
indmin
/indmax
fornece o índice m (e, portanto, o valor de i ) do arranjo ótimo, que é m por ⌈n / m⌉ . Os laços são quebrados pela primeira ocorrência, que corresponde ao valor mais baixo de i , portanto, o valor mais alto de j - i e, portanto, o valor mais baixo de ij - n (cadeiras vazias).fonte
JavaScript (ES6) 74
78Edite mantendo o resultado temporário como uma matriz em vez de 2 vars, emprestado da resposta de Thiht
Menos golfe
Teste
fonte
PHP, 129 bytes
Ungolfed:
fonte
PHP, 104 bytes
O algoritmo que resolve esse problema é simples e provavelmente é usado por outras respostas em linguagens semelhantes ao PHP (JavaScript, fe):
n
é grande o suficiente (onden
está o valor de entrada); a pontuação do arranjo computado na primeira iteração (1, n
) é(n-1)+0
;1
en
; calcule a altura mínima comoceil(n/width)
, calcule a pontuação do arranjo usando a fórmula fornecida na pergunta (ieabs(width - height) + (width * height - n)
); se a pontuação for melhor do que a melhor pontuação anterior, lembre-se da largura, altura e nova pontuação; nos laços, use o valor dewidth * height - n
para o arranjo atual e o melhor arranjo anterior para detectar o novo melhor arranjo;Após o golfe, esse algoritmo produz algo parecido com este (incluído aqui para facilitar a leitura):
Ele usa 137 bytes (quando colocados em uma única linha) e está longe dos 104 bytes anunciados no título. Provavelmente, o código pode ser reduzido por outros 2-3 bytes, mas a grande fonte de aprimoramento está em outro lugar: nos detalhes do algoritmo.
O algoritmo revisado:
Existem vários lugares onde o algoritmo pode ser aprimorado removendo código inútil.
1
para$n
; para a velocidade, a largura ($i
) deve iterar entre1
efloor(sqrt($n))
mas isto faz com que o código de ainda mais tempo, em vez de encurtando-o; mas se a largura não excedersqrt($n)
, a altura mínima ($j
) sempre será maior quesqrt($n)
(o produto deve ser pelo menos$n
);$i <= $j
(largura <= altura) como condição de término para o loop; Desta forma, a largura irá iterar a partir1
defloor(sqrt($n))
ea altura terá valores começando com$n
e indo paraceil(sqrt($n))
(não necessariamente todos eles);abs(width - height)
é sempreheight - width
($j-$i
); 5 bytes salvos desta maneira;$n
é usado no cálculo da pontuação (o número de assentos desocupados éwidth * height - n
), mas não é necessário; a pontuação não precisa ser exibida, é calculada apenas para comparação dos arranjos; removendo- n
da fórmula de pontuação, salvamos outros 3 bytes (o código PHP é-$n
) sem perder nada;height - width + width * height
($j-$i+$i*$j
);height - width
parte da pontuação diminui a cada passo;||$c==$s&&$i*$j<$w*$h
- muitos bytes);-$n
fórmula da pontuação, a pontuação do primeiro arranjo (1x$n
) é$n-1+1*$n
(ie2*$n-1
); o valor inicial da melhor pontuação ($s
) pode ser qualquer valor maior ou igual a2*$n
; a primeira iteração tem uma pontuação melhor e se torna o melhor arranjo, permitindo que o algoritmo seja executado sem problemas de inicialização.O novo código ( 104 bytes ), após a aplicação das melhorias descritas acima, é:
Está embrulhado aqui para facilitar a leitura. Anexe o código acima com o marcador PHP
<?php
(tecnicamente, ele não faz parte do código), coloque-o em um arquivo (digamosarrange-your-chairs.php
) e execute-o com um número inteiro maior que zero como argumento. Ele exibirá a largura e a altura do arranjo computado, separadas por vírgula:Outra solução (116 bytes)
Outra solução que usa um algoritmo diferente:
Ele coloca todas as combinações de pelo menos
$n
assentos em uma lista associativa; a chave é a representação em texto do arranjo, o valor é a pontuação do arranjo. Em seguida, classifica a lista (crescente por valor) e obtém a chave da primeira entrada.Mais um (115 bytes)
Esta é a versão PHP da resposta de @ Neil (JavaScript / ES6, 85 bytes).
Existem algumas diferenças visíveis devido aos recursos de cada idioma:
n
valores (indefinidos) e depois usa suas chaves para iterar de0
paran-1
; incrementai
(d=(n+i++)/i|0
) para iterar de1
paran
; a solução PHP não precisa ser incrementada; ele usarange()
para gerar uma matriz e usa os valores gerados (1
paran
) para iterar;(n+i)/i
e converte o valor para inteiro usando|0
para obter o menor inteiro maior quen/i
; a resposta do PHP resolve esse problema facilmente com a função PHPceil()
; O JavaScript também fornece,Math.ceil()
mas usa 5 bytes a mais que a solução encontrada por Neil;array_map()
que é de alguma forma semelhante ao JS,Array.map()
mas não ajuda aqui; sua sintaxe é detalhada,foreach
produz um código mais curto; é maior que o código JS;||
não é possível no PHP porque não possui o operador vírgula; Traduzia||b||c
paraif(!a&&!b)c
então, porquea
eb
são comparações, neguei seus operadores (substituídos<
por>=
); isso também produz código maior que a versão JS;$
.As versões simples de todas as soluções e o conjunto de testes podem ser encontradas no Github .
fonte
JavaSCript (ES6), 83 bytes
fonte
m
para compensar.Julia, 87
Eu acho que este é um passo na direção de encontrar um função mágica para o problema:
Olha apenas pares
(i, j=(i+n)/(i+1))
ou(i, j+1)
fonte
n
lugar algum e não parece estar recebendo informações.n
como entrada. Seria necessário envolvê-lon->...
. É bom que você possa fazê-lo funcionar.Oracle SQL 11.2, 173 bytes
Sem golfe
fonte
Q 58 bytes
Lamba que calcula o custo mínimo para um determinado valor (x) e retorna uma sequência de dois valores (largura, altura)
Adicionar nome a esse lambda requer outros dois caracteres (ex f: {..} em vez de {..})
Teste
onde {..} é a lambda. Leia como "aplica lambda a cada valor de 1 + primeiras 100 ints" (em outras palavras, a cada valor 1..100)
Gera
Explicação
O lamdba aninhado
{((b<a)?1b)#+(b:-_-x%a;a:1+!x)}
gera todos os pares candidatos (largura, altura) para cadeiras x como duas seqüências (w1 w2 w3 ..; h1 h2 h3 ..) (larguras e alturas). Leia da esquerda para a direita, mas avalia da direita para a esquerdaa:1+!x
gera valores 1..x e atribui essa sequência a um-_-
é negar andar negar e implementar ceil (ceil não é um primitivo da linguagem)b:-_-x%a
aplica teto a cada valor de x dividido por qualquer item im a e atribui a sequência resultante a b. Em outras palavras, b é teto cada x divididoPor cada 1..x+(b;a)
retorna uma secuência composta pelas seq ae seq b, e depois a vira (o resultado é uma sequência de pares em que o par i contém o elemento i de ae o elemento i de b)b<a
compara item por item de bec, e gera uma segurança de valores lógicos (true = 1b para cada índice em que b [i]s?x
retorna a primeira posição do item x na sequência s. Com(b<a)?1b
Buscamos 1b (valor verdadeiro) na sequência resultante da comparação be ae obtemos a primeira posição em que bn#s
leva n primeiros n itens de seq s. Queremos descartar pares duplicados, então paramos quando o primeiro item de um par <segundo item (por exemplo, considere 13,1, mas não 1,13).Como efeito colateral, cada par da sequência resultante tem uma distância decrescente entre aeb (ex (13 1; 7 2; 5 3; 4 4)
O par candidato gerado pelo lambda aninhado é designado a c. Em seguida, invertemos c (obtém b, a novamente) e aplicamos duas funções a esse argumento:
*/
multiplica e-/
subtrai. O resultado(-/;*/)@\:+c
é a diferença e o produto de cada par.+/
é soma total e calcula o custo final. O custo de cada patir é atribuído a d& / é mínimo, então
&/
d é o custo mínimo. Comd?&/d
encontramos a primeira ocorrência de custo mínimo em d, e com c @ .. recuperamos o par nessa posição. Como cada par é distante decrescente entre a e n, o primeiro mínimo encontrado tem o máximo distante entre outros pares mínimos, então aplicamos a regra do empate corretamentefonte