Vecteurs euclidiens

14

Étant donné l'art ASCII de deux vecteurs, trouvez la magnitude et le degré du vecteur résultant.


Contribution

Celui-ci peut être reçu via STDIN, lu à partir d'un fichier local ou fourni via un appel de fonction. Voici un exemple d'une entrée à deux vecteurs:

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

Cela représente un changement de 4 unités au nord et 7 unités à l'est. Le point de départ de chaque entrée sera représenté par un x(décimal 120).

  • Tous les vecteurs sont des lignes horizontales ou verticales.

  • Chaque vecteur possède l'un de ces quatre points de terminaison:, ^v<>et est composé d'un tiret ( -, décimal 45) ou d'une barre verticale ( |, décimal 124).

  • Les points vides de l'avion sont remplis d'espaces ( , 32 décimaux).

  • L'entrée peut être unique x.

  • Les vecteurs adjacents sont toujours perpendiculaires les uns aux autres.

  • Tous les vecteurs sont de bout en bout.


Production

Ce sera le déplacement du point résultant (distance du point de départ) et le degré de déplacement par rapport au point de départ.

Pour l'entrée ci-dessus, la sortie doit être des 8.06unités et des 60.3degrés. Chacun devrait avoir exactement 3 chiffres significatifs. Voici quelques exemples de nombres à 3 chiffres significatifs:

  • 1,00
  • 60,1
  • 453
  • 7.08
  • 4,50
  • 349

Toutes les mesures unitaires seront <= 999.


Ces nombres doivent être sortis dans le format ci-dessous. C'est en utilisant les chiffres ci-dessus.

8.06 units @ 60.3 degrees

Cela peut être suivi d'un seul espace de fin ou d'une nouvelle ligne.


Si l'entrée est unique x, sans déplacement et donc sans angle de déplacement, la sortie doit être soit une ligne vide (un seul caractère de nouvelle ligne), soit au format suivant:

0 units @ - degrees

Si vous essayez de vous qualifier pour le bonus, la direction devrait également l'être -.


Dans le cas où les bonus 2, 3 ou les deux sont terminés, la sortie doit suivre le modèle ci-dessous et respecter les mêmes restrictions que ci-dessus.

8.06 units @ 60.3 degrees NE

Les degrés doivent être mesurés selon le plan standard.

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

0degrés est est, 1 - 89degrés est nord-est, 90est nord, etc.


Bonus

Les éléments suivants valent au total -50%.

  1. Prenez un bonus de -10% pour chaque vecteur supplémentaire qui peut être manipulé. Ce bonus peut être appliqué jusqu'à 3 fois. Les vecteurs ne se chevaucheront ni ne se croiseront jamais.

  2. Prenez un bonus de -10% si votre sortie inclut la direction cardinale de l'angle (nord, sud, est, ouest).

  3. Bénéficiez d'un bonus de -10% si votre sortie inclut les directions intermédiaires de l'angle (nord-est, nord-ouest, sud-est, sud-ouest).


Exemples

Dans:

x---->
     |
     v

En dehors:

5.39 units @ 338 degrees

En option SE


Dans:

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

En dehors:

15.3 units @ 169 degrees

En option NW


Dans:

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

En dehors:

2.24 units @ 297 degrees

En option SE


Exemples (plusieurs vecteurs)

Dans:

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

En dehors:

16.3 units @ 349 degrees

En option SE


Dans:

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

En dehors:

8.54 units @ 159 degrees

En option NW


Dans:

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

En dehors:

6.32 units @ 162 degrees

En option NW

Portes Zach
la source
Les vecteurs auront-ils jamais une composante nulle dans une direction? Si oui, à quoi devrait servir la sortie x? Quelle est la frontière entre le nord et le nord-ouest?
lirtosiast
J'ai ajouté cette information. Merci de l'avoir signalé! @ThomasKwa
Zach Gates
Vous devez ajouter un cas de test où il n'y a qu'un seul vecteur, par exemple x-->. Les vecteurs peuvent-ils se croiser?
lirtosiast
L'entrée régulière sera deux vecteurs. La seule exception est le vide x. Il peut y en avoir plus de deux (si vous tentez de compléter le bonus), mais pas moins. Je travaille sur des exemples pour plusieurs entrées vectorielles. En aucun cas, les vecteurs ne se croiseront. @ThomasKwa
Zach Gates
Je les ai ajoutés. @ThomasKwa
Zach Gates

Réponses:

2

JavaScript (ES6), 305 octets - 50% de bonus = 152,5 points

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`)

Explication

L'entrée doit être complétée par des espaces. Utilise tous les bonus.

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
)

Tester

user81655
la source
3

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

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']

Explication

Recherche les positions de début et de fin en regardant chaque caractère dans l'entrée.

Le début est x

La fin se trouve en regardant chaque flèche (<>^v ) et leurs voisins. Si les voisins sont des vecteurs continus, ignorez. Sinon, c'est la fin.

Regardez les voisins perpendiculaires à la direction de la flèche.

S'ils contiennent une ligne perpendiculaire, alors c'est un vecteur continu.

Exemples ( _indique l'espace):

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

___   
->_   (end)
___   

_|_   
->_   (not end)
___ 

___   
->|   (end)
___ 

---   
->_   (end)
___ 

Parce que le point final est trouvé, il peut y avoir n'importe quel nombre de vecteurs ( bonus de 30% ).

TFeld
la source
Êtes-vous sûr que cela fonctionne en python 2? De plus, vous pouvez remplacer "de l'importation mathématique " par "de l'importation mathématique " (supprimez l'espace).
Rɪᴋᴇʀ
@RikerW Cela fonctionne pour moi. Ideone: ideone.com/9j86yj utilise \ncomme sauts de ligne ...
TFeld
Bravo, avec une belle explication des "voisins". J'étais un peu inquiet de votre utilisation input()et de l'encapsulation correspondante de l'entrée avec "", mais il ne semble pas y avoir de règle contre!
Tim Pederick