Dada uma lista de coordenadas 2d (x, y), determine quantos quadrados de unidade (comprimento da aresta 1 unidade) podem ser formados usando as coordenadas.
- A entrada será uma matriz de 0 ou mais pares de coordenadas:
por exemplo, em JavaScript:numofsq([[0,0], [1,0], [1,1], [0,1]])
- Nenhuma coordenada duplicada na entrada
- A ordem de entrada será aleatória (coordenadas 2d aleatórias).
- Formulário de coordenadas: [coordenada x, coordenada y] (duh)
- Ordem das coordenadas: [0,0], [1,0], [1,1], [0,1] e [0,0], [0,1], [1,1], [1,0 ] denota o mesmo quadrado da unidade (a ser contado apenas uma vez)
- As coordenadas podem ser números inteiros negativos ou positivos (duh)
- A função retornará apenas o número de quadrados de unidade possível, 0 ou mais.
Casos de teste:
Input Coordinates Pairs Expected Output
[0,0], [0,1], [1,1], [1,0], [0,2], [1,2] 2
[0,0], [0,1], [1,1], [1,0], [0,2], [1,2], [2,2], [2,1] 3
[0,0], [0,1], [1,1], [1,0], [0,2], [1,2], [2,2], [2,1], [2,0] 4
[0,0], [0,1], [1,1], [1,0], [0,2], [1,2], [2,2], [2,1], [2,0], [9,9] 4
Alerta de spoiler: solução aqui em diante [JS]
Abordagem sem força de golfe, rápida e suja, com força bruta (incluída para fornecer algumas instruções).
//cartesian distance function
function dist(a, b) {
if (b === undefined) {
b = [0, 0];
}
return Math.sqrt((b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1]));
}
//accepts 4 coordinate pairs and checks if they form a unit square
//this could be optimized by matching x,y coordinates of the 4 coordinates
function isUnitSquare(a) {
var r = a.slice(),
d = [],
c = [],
i,
j = 0,
counter = 0;
for (i = 1; i < 4; i++) {
if (dist(a[0], a[i]) === 1) {
d.push(a[i]);
r[i] = undefined;
counter++;
}
}
r[0] = undefined;
c = d.concat(r.filter(function(a) {return undefined !== a}));
if (dist(c[0], c[1]) === 1) {j++};
if (dist(c[1], c[2]) === 1) {j++};
if (dist(c[2], c[0]) === 1) {j++};
return counter === 2 && j === 2;
}
//a powerset function (from rosetta code)
//however, we will need only "sets of 4 coordinates"
//and not all possible length combinations (sets of 3 coords or
//sets of 5 coords not required). Also, order doesn't matter.
function powerset(ary) {
var ps = [[]];
for (var i=0; i < ary.length; i++) {
for (var j = 0, len = ps.length; j < len; j++) {
ps.push(ps[j].concat(ary[i]));
}
}
return ps;
}
//so to capture only sets of 4 coordinates, we do
var res = powerset([[0,0], [0,1], [1,1], [1,0], [0,2], [1,2], [2,2], [2,1], [2,0]])
.filter(function (a) {return a.length === 8;});
//and a little bit of hoopla to have a nice set of sets of 4 coordinates.
//(Dizzy yet? Wait for the generalized, 3D, cube of any edge length version ;))
var squareQuads = res.map(function(ary) {
return ary.join().match(/\d\,\d/g)
.map(function(e) {
return [+e.split(',')[0], +e.split(',')[1]];
});
});
//Finally, the last bit
var howManyUnitSquares = 0;
squareQuads.map(function(quad) {
if (isUnitSquare(quad)) {
howManyUnitSquares++;
}
});
console.log(howManyUnitSquares);
//Cleaning up and putting those in-line stuff into a function
function howManySquares(r) { //r = [[x,y], [x,y], [x,y], [x,y], ......];
var res = powerset(r)
.filter(function (a) {return a.length === 8;});
var squareQuads = res.map(function(ary) {
return ary.join().match(/\d\,\d/g)
.map(function(e) {
return [+e.split(',')[0], +e.split(',')[1]];
});
});
var answer = 0;
squareQuads.map(function(quad) {
if (isUnitSquare(quad)) {
answer++;
}
});
return answer;
}
[-1,0],[0,-1],[1,0],[0,1]
um quadrado?[-2,0],[0,-2],[2,0],[0,2]
tem um comprimento de borda de2
. Quadrado?Respostas:
APL (Dyalog), 30
Bem, na maioria dos casos, a legibilidade e a contagem de caracteres são proporcionais.
Saída de amostra
Explicação
Portanto, 4 pontos forma um quadrado de unidade se, e somente se, suas posições relativas forem (1,1), (1,2), (2,1), (2,2),
{(2-/⍵)≡2-/,⍳2 2}
é uma função que retorna 1 ou 0 (true / false) dado um conjunto de 4 pontos como entrada com base em se eles estão em posições relativas e classificados na ordem (1,1), (1,2), (2,1), (2,2):⍳2 2
Gere um 2 × 2 matriz dos pontos (1,1), (1,2), (2,1), (2,2),
Desvendar essa matriz para uma matriz de pontos A2-/
subtração pareada reduz: (1,1) - ( 1,2); (1,2) - (2,1); (2,1) - (2,2), que fornece a matriz [(0, -1), (- 1,1), (0, -1)] A(2-/⍵)
subtração em pares reduz a entrada≡
Verifique se as duas matrizes iguaisO programa principal
⎕
Pega entrada e avalia. Coisas como são(0 0)(0 1)(1 0)(1 1)
avaliadas para uma matriz aninhada (equivalente a[[0,0],[0,1],[1,0],[1,1]]
em JS).⊂¨
Para cada ponto (¨
), coloque-a em um escalar (⊂
) ([[[0,0]],[[0,1]],[[1,0]],[[1,1]]]
).∘.,⍨⍣2
Para cada par de elementos da matriz, concatene-os para formar uma nova matriz. ([ [[0,0],[0,0]],[[0,0],[0,1]]...
) Repita uma vez. Isso fornece todos os conjuntos de 4 pontos que podem ser feitos usando os pontos fornecidos. Em alguns desses conjuntos, o mesmo ponto seria usado várias vezes, mas estes não seriam quadrados de unidades, portanto, não é necessário desperdiçar as teclas pressionadas para removê-las. (,
concatena 2 matrizes,∘.
significa "faça isso para cada par de elementos",⍨
significa "use o operando direito como operandos esquerdo e direito" e⍣2
significa "faça isso duas vezes"),
Como a operação anterior daria uma matriz 4-dimensional (observe que matrizes aninhadas e matrizes multidimensionais são coisas diferentes no APL), temos que desvendá-lo para obter uma matriz de conjuntos (de 4 pontos).¨
Para cada um dos conjuntos,{...}
execute a função mencionada acima. O resultado seria uma matriz de 0s e 1s indicando se o conjunto é um quadrado de unidade. Observe que, como a função também verifica a ordem, as duplicatas são eliminadas.+/
Finalmente, some a matriz resultante para obter a contagem.fonte
Mathematica 65 caracteres
Testes
Explicação
Gera todos os subconjuntos de 4 pontos e verifica todas as distâncias entre pontos. As distâncias entre pontos classificadas para um quadrado unitário são: `{1, 1, 1, 1, √2, √2}.
Length
então conta o número de quadrados da unidade.fonte
g
?f=Count[#-#[[1]]&/@(Sort/@#~Subsets~{4}.{1,I}),{0,I,1,1+I}]&
Ruby,
164161153147 caracteresNa verdade, é muito legível, exceto pela parte que testa se é um quadrado de unidade ou não.
Provavelmente muitas melhorias possíveis, tentando encontrá-las agora.
Amostras (todas elas funcionam):
Talvez eu consiga encontrar um truque
transpose
, mas estou tentando há um tempo e não consigo. Aqui está o que ele faz:fonte
Python, 61 caracteres
Amostra:
fonte
Mathematica, 56 caracteres
fonte