Vetores euclidianos

14

Dada a arte ASCII de dois vetores, encontre a magnitude e o grau do vetor resultante.


Entrada

Isso pode ser recebido via STDIN, lido de um arquivo local ou fornecido através de uma chamada de função. Aqui está um exemplo de uma entrada de dois vetores:

^------>
|
|
|
x

Isso representa uma mudança de 4 unidades ao norte e 7 unidades a leste. O ponto inicial de cada entrada será representado por um x(decimal120 ).

  • Todos os vetores são linhas horizontais ou verticais.

  • Cada vetor possui um desses quatro pontos finais: ^v<>e é composto de um traço ( -decimal 45) ou uma barra vertical (| decimal 124).

  • Os pontos vazios no plano são preenchidos com espaços ( , decimal 32).

  • A entrada pode ser única x.

  • Os vetores adjacentes são sempre perpendiculares entre si.

  • Todos os vetores são tip-to-tail.


Resultado

Esse será o deslocamento do ponto resultante (distância do ponto inicial) e o grau em que ele foi movido, em relação ao ponto inicial.

Para a entrada acima, a saída deve ser 8.06unidades e 60.3graus. Cada um deve ter exatamente 3 números significativos. Aqui estão alguns exemplos de números com três dígitos significativos:

  • 1,00
  • 60,1
  • 453
  • 7.08
  • 4.50
  • 349

Todas as medidas da unidade serão <= 999.


Esses números devem ser impressos no formato abaixo. Isso está usando os números acima.

8.06 units @ 60.3 degrees

Isso pode ser seguido por um único espaço à direita ou nova linha.


Se a entrada for única x, sem deslocamento e, portanto, sem ângulo de deslocamento, a saída deverá ser uma linha vazia (um único caractere de nova linha) ou no seguinte formato:

0 units @ - degrees

Se você está tentando se qualificar para o bônus, a direção também deve ser -.


Caso os bônus 2, 3 ou ambos sejam concluídos, a saída deve seguir o modelo abaixo e obedecer às mesmas restrições que as anteriores.

8.06 units @ 60.3 degrees NE

Os graus devem ser medidos de acordo com o plano padrão.

       90
  135  |  45
      \|/
180 ---x---- 0
      /|\
  225  |  315
      270

0graus é leste, 1 - 89graus é nordeste, 90é norte, etc.


Bónus

A seguir, vale um total de -50%.

  1. Receba um bônus de -10% para cada vetor adicional que puder ser manuseado. Este bônus pode ser aplicado até 3 vezes. Os vetores nunca se sobrepõem ou se cruzam.

  2. Receba um bônus de -10% se sua saída incluir a direção cardinal do ângulo (norte, sul, leste, oeste).

  3. Receba um bônus de -10% se sua saída incluir as direções intermediárias do ângulo (nordeste, noroeste, sudeste, sudoeste).


Exemplos

Dentro:

x---->
     |
     v

Fora:

5.39 units @ 338 degrees

Opcionalmente SE


Dentro:

<--------------^
               |
               |
               x

Fora:

15.3 units @ 169 degrees

Opcionalmente NW


Dentro:

x
|
|<-----^
|      |
v------>

Fora:

2.24 units @ 297 degrees

Opcionalmente SE


Exemplos (vários vetores)

Dentro:

x--->
    |
    |
    v----------->

Fora:

16.3 units @ 349 degrees

Opcionalmente SE


Dentro:

<-------^
|       |
|       |
v       |
        |
        |
        x

Fora:

8.54 units @ 159 degrees

Opcionalmente NW


Dentro:

^-->
|  |
|  v
|
<--------x

Fora:

6.32 units @ 162 degrees

Opcionalmente NW

Zach Gates
fonte
Os vetores terão um componente zero em uma direção? Nesse caso, para que serve a saída x? Qual é o limite entre o Norte e o Noroeste?
lirtosiast
Eu adicionei essa informação. Obrigado por apontar isso! @ThomasKwa
Zach Gates
Você deve adicionar um caso de teste em que haja apenas um vetor, por exemplo x-->. Os vetores podem se cruzar?
precisa saber é o seguinte
A entrada regular será dois vetores. A única exceção é a vazia x. Pode haver mais de dois (se tentar completar o bônus), mas não menos. Estou trabalhando em exemplos para várias entradas de vetor. Em nenhuma entrada os vetores cruzarão. @ThomasKwa
Zach Gates
Eu os adicionei. @ThomasKwa
Zach Gates

Respostas:

2

JavaScript (ES6), 305 bytes - bônus de 50% = pontuação 152,5

v=>(l=v.search`
`+1,s=v.search`x`,u=0,d="-",v.replace(/[<>v^]/g,(p,i)=>{c=o=>v[i+o]!=q;with(Math)if(p<"?"?c(l,q="|")&c(-l):c(1,q="-")&c(-1))d=(atan2(x=i%l-s%l,y=(i/l|0)-(s/l|0))*180/PI+270)%360,u=sqrt(x*x+y*y)}),u[p="toPrecision"](3)+` units @ ${d[p](3)} degrees`)

Explicação

A entrada deve ser preenchida com espaços. Usa todos os bônus.

v=>(
  l=v.search`
`+1,                                                     // l = line length
  s=v.search`x`,                                         // s = index of start point
  u=0,                                                   // u = units
  d=                                                     // d = degrees
  w="-",                                                 // w = cardinal direction
  v.replace(/[<>v^]/g,(p,i)=>{                           // for each endpoint
    c=o=>v[i+o]!=q;                                      // compares cell at offset to char
    with(Math)                                           // save having to write "Math."
      if(p<"?"?c(l,q="|")&c(-l):c(1,q="-")&c(-1))        // check for line branching off
        d=(atan2(
          x=i%l-s%l,                                     // x = relative x
          y=(i/l|0)-(s/l|0)                              // y = relative y
        )*180/PI+270)%360,                               // convert to degrees
        u=sqrt(x*x+y*y),
        w="N S"[sign(y)+1]+"W E"[sign(x)+1]              // get cardinal direction
  }),
  u[p="toPrecision"](3)+` units @ ${d[p](3)} degrees `+w // format output
)

Teste

user81655
fonte
3

Python 2, 238,5 ( 594 562 482 477-50%) bytes

from math import*
def F(x):s='%.3g'%x;return[[s+'.',s]['.'in s].ljust(4,'0'),s][x>99]
I=input()
V=I.split('\n');N=len(V)
l=max(len(x)for x in V)
q=[' '*(l+2)];V=q+[' '+x.ljust(l+1)for x in V]+q
for k in range(N*l):
 i,j=k/l,k%l;c=V[i+1][j+1]
 if c in'<>^v'and['|'not in zip(*V)[j+1][i:i+3],'-'not in V[i+1][j:j+3]][c>'?']:a,b=i,j
 if c=='x':A,B=i,j
Y=A-a;X=b-B;a=atan2(Y,X)/pi*180%360
print[F(hypot(X,Y))+' units @ '+F(a)+' degrees '+' NS'[cmp(Y,0)]+' EW'[cmp(X,0)],''][I=='x']

Explicação

Localiza as posições inicial e final observando cada caractere na entrada.

Iniciar é x

O fim é encontrado olhando cada flecha ( <>^v) e seus vizinhos. Se os vizinhos continuarem vetores, ignore. Senão, este é o fim.

Olhe para os vizinhos perpendiculares à direção da seta.

Se eles contêm uma linha perpendicular, então é um vetor contínuo.

Exemplos ( _indica espaço):

_#_   
->_   Neighbors marked by #
_#_ 

___   
->_   (end)
___   

_|_   
->_   (not end)
___ 

___   
->|   (end)
___ 

---   
->_   (end)
___ 

Como o ponto final é encontrado, pode haver qualquer número de vetores ( bônus de 30% ).

TFeld
fonte
Você tem certeza de que isso funciona no python 2? Além disso, você pode alterar "de importação matemática " para "de importação matemática " (remova o espaço).
Rɪᴋᴇʀ
@RikerW Funciona para mim. : Ideone ideone.com/9j86yj usos \ncomo quebras de linha ...
TFeld
Bem feito, com uma boa explicação dos "vizinhos". Fiquei um pouco preocupado com o uso input()e o empacotamento correspondente da entrada com "", mas não parece haver uma regra contra isso!
precisa saber é o seguinte