Desafio
Dada uma matriz estocástica esquerda ou direita, em que o limite em que x se aproxima do infinito da matriz à potência de x se aproxima de uma matriz com todos os valores finitos, retorne a matriz à qual a matriz converge. Basicamente, você deseja continuar multiplicando a matriz por si só até que o resultado não seja mais alterado.
Casos de teste
[[7/10, 4/10], [3/10, 6/10]] -> [[4/7, 4/7], [3/7, 3/7]]
[[2/5, 4/5], [3/5, 1/5]] -> [[4/7, 4/7], [3/7, 3/7]]
[[1/2, 1/2], [1/2, 1/2]] -> [[1/2, 1/2], [1/2, 1/2]]
[[1/3, 2/3], [2/3, 1/3]] -> [[1/2, 1/2], [1/2, 1/2]]
[[1/10, 2/10, 3/10], [4/10, 5/10, 6/10], [5/10, 3/10, 1/10]] -> [[27/130, 27/130, 27/130], [66/130, 66/130, 66/130], [37/130, 37/130, 37/130]]
[[1/7, 2/7, 4/7], [2/7, 4/7, 1/7], [4/7, 1/7, 2/7]] -> [[1/3, 1/3, 1/3], [1/3, 1/3, 1/3], [1/3, 1/3, 1/3]]
Regras
- As brechas padrão se aplicam
- Você pode escolher se deseja uma matriz estocástica direita ou esquerda
- Você pode usar qualquer tipo de número razoável, como valores flutuantes, racionais, decimais de precisão infinita, etc.
- Isso é código-golfe , portanto, o envio mais curto em bytes para cada idioma é declarado vencedor em seu idioma. Nenhuma resposta será aceita
Respostas:
R ,
4443 bytesExperimente online!
Apenas continua se multiplicando até encontrar uma matriz fixa. Aparentemente
X!=(X=X%*%m)
, a comparação é reatribuídaX
, o que é legal.Obrigado ao @Vlo por remover um byte; apesar de riscado 44 ainda é regular 44.
fonte
function(m){ while(any(m!=(m=m%*%m)))0 m}
que não funciona. Imprecisões numéricas que impedem que a condição de terminação seja acionada?Octave ,
4542.35 bytesExperimente online!
Economizou 3 bytes graças a Giuseppe e mais 7 graças a Luis Mendo!
Isso usa que o vetor próprio correspondente ao valor próprio 1 (também o valor máximo máximo) é o vetor da coluna que é repetido para cada valor da matriz limitante. Temos que normalizar o vetor para ter a soma 1 para que seja estocástico, depois basta repeti-lo para preencher a matriz. Não sou muito versado em golfe no Octave, mas não consegui encontrar uma maneira funcional de fazer a multiplicação repetida, e um programa completo parece que sempre será mais longo do que isso.
Podemos usar
any(A)
uma vez que, a partir das restrições, sabemos que a matriz deve descrever uma cadeia de Markov irredutível e, portanto, cada estado deve ser acessível a partir dos outros estados. Portanto, pelo menos um valor em cada coluna deve ser diferente de zero.fonte
eigs
sempre retorna o vetor próprio correspondente1
? Minha memória das cadeias de markov é um pouco confusa.eigs
retorna a partir do maior valor próprio. Além disso, obrigado pelo golfe!Língua Wolfram (Mathematica) , 14 bytes
Flutuadores de saída:
Experimente online!
Wolfram Language (Mathematica) , 30 bytes
Frações de saída:
Experimente online!
fonte
Gelatina , 6 bytes
Este é um programa completo.
Experimente online!
fonte
APL (Dyalog) ,
186 bytes12 bytes salvos graças a @ H.PWiz
Experimente online!
fonte
+.×⍨⍣≡
por 6 bytes. Isto é, praça até que nada mudak / q, 10 bytes
k / q porque o programa é idêntico nos dois idiomas. O código é realmente apenas k / q idiomático.
Explicação
{..}
está fora da sintaxe lambda, comx
um parâmetro implícito$[x]
tem $ como operador de multiplicação de matriz binária, fornecendo apenas um parâmetro cria um operador unário que é multiplicado pela matriz de Markov/[x]
aplica a multiplicação esquerda até a convergência, começando com o próprio x.fonte
C (gcc) ,
207192190181176 bytes + 2 bytes de flag-lm
quinzedezessete evinte e dois bytes graças ao ceilingcat .return A;
.Experimente online!
fonte
Python 3 ,
7561 bytesExperimente online!
Nos casos de teste, existem imprecisões de flutuação, portanto os valores podem diferir um pouco das frações exatas.
PS.
numpy.allclose()
é usado porquenumpy.array_equal()
é mais longo e propenso a flutuações de imprecisões.-14 bytes Obrigado HyperNeutrino;) Ah, sim, esqueci o operador @; P
fonte
dot
vez dematmul
: Dx=n@n
: P tio.run/...f=
em frente porque é recursivamente chamado;)Java 8,
356339 bytes-17 bytes graças a @ceilingcat .
Definitivamente não é o idioma certo .. Maldita precisão de ponto flutuante ..
Explicação:
Experimente online.
fonte
float
/double
não tem a precisão de ponto flutuante adequada,java.math.BigDecimal
deve ser utilizada. E, em vez de simplesmente+-*/
, BigDecimals usar.add(...)
,.subtract(...)
,.multiply(...)
,.divide(...)
. Então, algo tão simples quanto7/10
se tornanew BigDecimal(7).divide(new BigDecimal(10))
. Além disso, o,scale,RoundingMode
nodivide
é necessário para valores com valores decimais 'infinitos' (como1/3
ser0.333...
). O método principal pode, é claro, ser jogado no golfe, mas eu não me incomodei quando fiz uma pesquisa e substituição para converter os carros alegóricos em BigDecimals.