Boucles et boucles et boucles

16

Le défi

Créez une fonction qui, lorsqu'elle reçoit une entrée d'art ASCII (dirigeant un chemin qui peut éventuellement boucler), génère la longueur de la boucle (s'il y en a une) et la longueur de la "queue" menant dans la boucle dans l'un des formulaires ci-dessous.


Contribution

Votre entrée doit être transmise à une fonction. Voici un exemple d'une entrée simple.

# --> # --> #
      ^     |
      |     |
      |     v
      # <-- #

Vous pouvez visualiser les blocs ci-dessus comme ceci

La "queue" est un élément, tandis que la boucle est longue de quatre.

Un plus difficile:

            # --> # --> #
            ^           |
            |           |
            |           v
      # --> # <-- #     # --> #
      ^           ^           |
      |           |           |
      |           |           v
# --> #           # <-- # <-- #

Production

Vous devez sortir via STDOUT ou l'alternative la plus proche de votre langue.

Vos deux entiers de sortie devraient être la longueur de la queue et la longueur de la boucle. Cette sortie peut prendre deux formes.

  1. une chaîne délimitée par des espaces: "2 10"
  2. un tableau d'entiers: [2, 10]

Règles

  • Chaque bloc, ou #, n'aura qu'un seul chemin loin de lui-même.

  • Chaque flèche est composée de deux segments de ligne et d'une tête.

  • Le bloc de départ sera toujours dans la colonne la plus à gauche.

  • L'entrée ne sera jamais qu'une boucle.


Exemple

# --> # --> # --> #
^     ^           |
|     |           |
|     |           v
#     # <-- # <-- #

Celui-ci a une longueur de queue de 2 et une longueur de boucle de 6. En dessous, la queue et la boucle sont séparées.

Queue

# -->
^
|
|
#

Boucle

# --> # --> #
^           |
|           |
|           v
# <-- # <-- #

Les sorties correctes sont [2, 6]et "2 6".

Si l'entrée n'est qu'une queue , la longueur de boucle est nulle.

# --> # --> # --> #
                  |
                  |
                  v
        <-- # <-- #

Les sorties correctes pour l'entrée ci-dessus sont [6, 0]et"6 0"

Portes Zach
la source
@orlp Je pense que vous confondez entrée et sortie.
Sanchises
1
L'entrée peut-elle avoir des morceaux de chemin supplémentaires déconnectés?
2015
Je pense que l'intro porte à confusion. Cela me fait penser que le problème sera lié à l'analyse de programme, alors qu'il s'agit de trouver un chemin dans l'art ASCII.
xnor
J'ai supprimé l'intro. C'était un peu déroutant / trompeur. @xnor
Zach Gates
3
Connexes: Où la flèche pointe-t-elle?
mınxomaτ

Réponses:

11

JavaScript (ES6), 221 229

Une fonction avec l'entrée en paramètre, sortie sous forme de chaîne via une fenêtre popup (alerte).

Scannez à plusieurs reprises l'entrée:
à chaque étape

  • retirer le bout de la queue
  • compter les «#» restants

Lorsqu'il n'y a plus de queue à supprimer, le nombre d'étapes jusqu'à présent est la taille de la queue et le nombre de '# restants est la taille de la boucle.

Toutes les nouvelles lignes à l'intérieur des backticks sont significatives et comptées

Testez l'exécution de l'extrait ci-dessous avec Firefox (pas Chrome, car il ne prend pas en charge ...)

F=s=>{s=`


${s}


`.split`
`.map(r=>[...r]);for(t=0,f=1;f;)s.map((r,y)=>r.map((c,x)=>c=='#'&&((r[x+2]+r[x-2]+s[y-1][x]+s[y+1][x]).match`[v<>^]`?++l:t+=(f=r[x-4]=r[x+4]=s[y-3][x]=s[y+3][x]=r[x]=1))),f=l=0);alert(t+' '+l)}

// Less golfed
U=s=>{
  s=`\n\n\n${s}\n\n\n`.split`\n`.map(r=>[...r])
  t=0
  do {
    f=l=0
    s.forEach((r,y) => {
      r.forEach((c,x) => {
        if (c == '#')
        {
          if (!(r[x+2] == '<' || r[x-2] == '>' || s[y-1][x] == 'v' || s[y+1][x] == '^'))
            t+=(f=r[x-4]=r[x+4]=s[y-3][x]=s[y+3][x]=r[x]=1)
          else
            ++l
        }
      })
    })
  } while(f)
  alert(t+' '+l)
}  

//Test

// Redefine console.log
alert=(...x)=>O.innerHTML+=x+'\n'

test=[`
# --> # --> #
      ^     |
      |     |
      |     v
      # <-- #`
,`
            # --> # --> #
            ^           |
            |           |
            |           v
      # --> # <-- #     # --> #
      ^           ^           |
      |           |           |
      |           |           v
# --> #           # <-- # <-- #`
,`
# --> # --> # --> #
^     ^           |
|     |           |
|     |           v
#     # <-- # <-- #`      
]

test.forEach(t=>(alert(t),F(t)))
<pre id=O></pre>

edc65
la source
... l'opérateur de propagation a-t-il raison? Vous pourriez vouloir le nommer de cette façon car il existe dans d'autres langues (comme groovy) par d'autres syntaxes (*: liste pour groovy). Belle solution quand même!
Aaron
1
+1 Je me disais «Il doit y avoir un moyen intelligent de le faire», est venu avec cette solution, pour faire défiler vers le bas jusqu'à cette réponse.
Sanchises
8

Rubis, 287 278 octets

->i{n={}
g=->x{n[x]||=[0,p]}
t=y=0
i.lines{|l|x=0
l.chars{|c|x+=1
'><'[c]&&(r=c.ord-61;s,d=[y,x-4*r],[y,x+2*r])
'^v'[c]&&(r=c<?_?1:-1;s,d=[y+r*3,x],[y-r,x])
s&&(g[s][1]=g[d])[0]+=1}
y+=1}
c,*_,s=n.values.sort_by{|v|v[0]}
l=n.size
s[0]>1?((t+=1;c=c[1])while c!=s):t=l-=1
[t,l-t]}

Essayez-le ici .

Cela crée un hachage (dictionnaire) de nœuds. Pour chaque nœud, le nombre de connexions entrantes et le nœud suivant (éventuellement nul) sont stockés.

Finalement:

  • S'il n'y a pas de nœud avec 2 connexions entrantes (ce qui signifie pas de boucle), retournez 0 pour la queue et le nombre de nœuds existants pour la boucle.
  • Sinon, commencez à itérer à partir du nœud avec 0 connexions entrantes (démarrage) via suivant -> ...-> suivant jusqu'à ce que le nœud avec 2 connexions entrantes (démarrage de boucle) soit atteint. Renvoyez les comptes appropriés.

La version lisible du code est disponible ici .

Cristian Lupascu
la source
2

Rubis, 276

->s{a=k=w=s.index(r='
')*2+2
s=r*w+s+r*w
(s.size).times{|i|s[i,2]=='
#'&&(s[3+j=i+1]+s[j+w]+s[j-w]).strip.size<2&&(a=[j]
d=0
loop{("|-|-"[d])+?#=~/#{s[k=j+[-w,3,w,-3][d]]}/?(a.include?(k)&&break;a<<(j=k);d-=1):d=(d+1)%4}
)}
u=a.size
v=a.index(k)
t=(u-v)/4*2
print u/2-t," ",t}
Level River St
la source