Cálculo da resistência (Nerd Sniping)

10

Boa tarde golfistas,

Nosso desafio de hoje é inspirado nos quadrinhos 356 e 370 do XKCD . Vamos escrever um programa para calcular a resistência de um grupo de resistores. Um aviso de que isso é quase difícil o suficiente para justificar ser um desafio de código, no entanto, acho que existe uma certa arte em escrever programas um pouco mais complexos em um formato de golfe. A menor quantidade de caracteres vence.

O cálculo da resistência se baseia nas duas fórmulas a seguir:

  • Se os resistores estiverem em série, a resistência é a soma da resistência de cada resistor
  • Se os resistores estão em paralelo, a resistência é o inverso da soma do inverso da resistência de cada resistor

Então - por exemplo:

Exemplo de cálculo de resistência

Seu desafio é, na menor quantidade de caracteres possível, calcular a resistência de um grupo de até 64 resistores. Peço desculpas pela complexidade, principalmente pelas regras de entrada. Tentei defini-los de tal maneira que todos os idiomas sejam utilizáveis.

  • Cada resistor será conectado a 2 ou mais outros resistores.

  • A entrada é garantida como válida, com apenas uma entrada e um ponto de saída, que conectará

  • A rede será paralela em série para evitar a necessidade de mais matemática do que o que é apresentado

  • A entrada será via arquivo, argumento ou stdin, dependendo do que for apropriado para o seu idioma.

  • A entrada consistirá em uma série de instruções separadas com nova linha ou barra, consistindo em um número inteiro da resistência do resistor e espaços que separam os IDs dos resistores aos quais um lado do resistor está conectado.

  • O ID do primeiro resistor será 1, incrementando em um para cada resistor sucessivo

  • O início sempre terá um ID 0

  • O resistor final sempre terá uma resistência de 0 ohms e apenas as conexões definidas em sua linha

Por exemplo:

Exemplo 2

Pode ser representado como

3 0
6 1
1 0
5 0
0 2 3 4
  • A saída pode ser para stdout ou arquivo. Pode ser representado de uma das seguintes maneiras:
    • Um número com no mínimo 2 casas decimais, seguido por uma nova linha
    • Uma fração que consiste em um número inteiro (o numerador), uma barra e outro número (o denominador), seguido por uma nova linha. A fração não precisa estar na sua forma mais baixa - 4/4 ou 10/8 são, por exemplo, aceitáveis. A fração deve ser precisa dentro de 1/100. Não há bônus por ser perfeitamente preciso - isso é uma muleta para permitir que idiomas sem operações de ponto fixo ou flutuante possam competir.

Espero que isso cubra todos os pontos. Boa sorte!

Lochok
fonte
/não é uma barra invertida. Você quis dizer `\` ou uma barra?
precisa
É permitido produzir resultados incorretos se a entrada não for uma rede paralela em série?
precisa
11
a ponte de Wheatstone não é série-paralelo se você substituir o voltímetro centro com um resistor
John Dvorak
11
os resistores sempre conectam aqueles com um ID mais baixo ou podem ser inseridos em qualquer ordem? É 1 2/1 0/0 1válido?
John Dvorak
9
O exemplo paralelo está errado. Deve ser 15/23, não 15/8.
Peter Taylor

Respostas:

6

APL 190

Origem do índice 1. O primeiro loop (s) combina todos os resistores conectados em série, o segundo (p) aqueles conectados em paralelo e a repetição para o primeiro loop para combinar quaisquer resistores paralelos agora em série. A especificação do resistor zero final parece ser redundante.

r←¯1↓⍎¨(c≠'/')⊂c        
o←⊃↑¨r                  
r←⊃1↓¨r                 
s:→(0=+/n←1=+/×r)/p     
n←↑n/i←⍳↑⍴r             
o[n-1]←+/o[n-0 1]       
o←(i←n≠i)/o             
r←i⌿r                   
r←r-r≥n                 
→s                      
p:n←1⍪2≠/r[;1]          
r←((⍴r),1)⍴r←¯1++\n~0   
o←∊1÷¨+/¨1÷¨n⎕penclose o
→(1<⍴o)/s               
3⍕o                     
' '  

Testado nos exemplos da pergunta mais um pouco mais complicado:

      Input: '5 0/3 1/1 2/0 2'
 9.000

      Input: '3 0/1 0/5 0/0 1 2 3'
 0.652

      Input: '3 0/6 1/1 0/5 0/0 2 3 4'
 0.763

      Input: '2 0/2 1/2 0/2 0/2 4/2 5/2 2 3 6/2 7/2 2 3 6/0 8 9'
 2.424
Graham
fonte
Sempre maravilhados com as respostas da APL - elas parecem absolutamente insanas. O resistor final era apenas para fornecer algo para os outros resistores se conectarem - um link final fictício. Bem feito!
lochok
Eu acho que você pode salvar alguns caracteres. Substitua as duas primeiras linhas por o←⊃↑¨r←¯1↓⍎¨(c≠'/')⊂c. Esse padrão é aplicável em alguns lugares.
FUZxxl
5

Python, 329 caracteres

import sys
N=[[1]]+[map(int,x.split())for x in sys.stdin]
N[-1][0]=1
n=len(N)
S=[set([i])for i in range(2*n)]
for x in range(n):
 C=S[2*x]
 for y in N[x][1:]:C|=S[2*y+1]
 for x in C:S[x]|=C
V=[0]*(2*n-1)+[1]
for k in range(999):
 for i in range(1,2*n-1):V[i]+=sum((V[j^1]-V[i])/N[j/2][0]for j in S[i])/9./len(S[i])
print 1/V[1]-2

Calcula a resistência fazendo um relaxamento de tensão no circuito. Primeiro, ele prende um resistor de 1 ohm no início e altera o último resistor de 0 ohm para 1 ohm. Em seguida, define a tensão de entrada para 0 e a tensão de saída para 1 volt. Após simular o fluxo de corrente através da rede, a resistência da rede é calculada usando a queda de tensão no primeiro resistor de 1 ohm.

Cada resistor recebe dois números, o número para o terminal esquerdo e o número para o terminal direito. O terminal esquerdo do resistor r é 2 * r e o terminal direito é 2 * r + 1. A entrada é usada para calcular Sos conjuntos de terminais conectados juntos. Cada terminal recebe uma tensão V[t]e um relaxamento é feito aumentando a tensão se a corrente estiver fluindo para um conjunto de terminais e diminuindo a tensão se a corrente estiver fluindo.

Keith Randall
fonte
2

(Este é um comentário, mas não posso fazer arte ascii em um comentário real ...)

Como é introduzido algo assim?

    --1--     --3--
   /     \   /     \
---       ---       --0--
   \     /   \     /
    --2--     --4--

Em particular, a que 3 e 4 estão conectados? 1 ou 2, ou ambos 1 e 2?

Keith Randall
fonte
Um e dois
lochok