language agnostic - CodeGolf: encuentra los caminos únicos
language-agnostic graph (9)
Aquí hay una idea bastante simple, en este pastebin he publicado algunos pares de números. Estos representan los nodos de un grafo dirigido. La entrada a stdin
será de la forma, (serán números, usaré un ejemplo aquí)
c d
q r
a b
b c
d e
p q
entonces xy
significa que x
está conectado a y
( no viceversa)
Hay 2 caminos en ese ejemplo. a->b->c->d->e
y p->q->r
.
Debe imprimir todas las rutas únicas de ese gráfico. La salida debe ser del formato.
a->b->c->d->e
p->q->r
Notas
- Puede asumir que los números se eligen de manera que una ruta no se interseca con la otra (un nodo pertenece a una ruta)
- Los pares están en orden aleatorio.
- Son más de 1 caminos, pueden ser de diferentes longitudes.
- Todos los números son menos de 1000.
Si necesita más detalles, por favor deje un comentario. Voy a enmendar según sea necesario.
Enchufe descarado
Para aquellos que disfrutan de Codegolf, por favor Comprométase en Area51 por su propio sitio :) (para aquellos que no lo disfruten, por favor apóyelo, así que nos mantendremos fuera de su camino ...)
Ocaml
402 caracteres
Básicamente una adaptación de la versión de Haskell, cuya longitud me sorprende. Ciertamente hay una manera de hacerlo mejor con Str
y / o la sintaxis revisada .
open List;;open String;; let q(a,b,p)=print_string(p^b^"/n")in let rec f(a,b,p)=function []->[a,b,p]|(x,y,q)::l when x=b->f(a,y,p^q)l|(x,y,q)::l when y=a->f(x,b,q^p)l|h::t->h::(f(a,b,p)t)in let t s=let i=index s '' ''in let h=sub s 0 i in h,sub s (i+1) ((length s) -i-1),h^"->"in let s=ref []in try while true do let l=read_line ()in s:=l::!s done with End_of_file->List.iter q(fold_right f(map t !s)[])
Ungolfed
open List;;
open String;;
let print (a,b,p) = print_string (p^b^"/n") in
let rec compose (a,b,p) = function
[] -> [a,b,p]
|(x,y,q)::l when x=b->compose (a,y,p^q) l
|(x,y,q)::l when y=a->compose (x,b,q^p) l
|h::t->h::(compose(a,b,p) t) in
let tokenize s = let i = index s '' '' in
let h = sub s 0 i in
h,sub s (i+1) ((length s) -i-1),h^"->" in
let lines = ref [] in
try
while true do
let l = read_line () in
lines := l::!lines
done
with
End_of_file-> List.iter print (fold_right compose (map tokenize !lines) [])
PHP - 155
foreach(file($argv[1])as$x){$x=explode('' '',$x);$g[$x[0]+0]=$x[1]+0;}
foreach($g as$a=>$b)if(!in_array($a,$g)){echo$a;while($b=$g[$b])echo"->$b";echo"/n";}
Todo el archivo se ve como:
<?php
error_reporting(0);
foreach(file($argv[1])as$x){$x=explode('' '',$x);$g[$x[0]+0]=$x[1]+0;}
foreach($g as$a=>$b)if(!in_array($a,$g)){echo$a;while($b=$g[$b])echo"->$b";echo"/n";}
Correr:
$ php graph.php graph.txt
Versión bonita:
$lines = file($argv[1]);
foreach ($lines as $line) {
$vertexes = explode('' '',$line);
$graph[$vertexes[0]+0] = $vertexes[1]+0; // the +0 forces it to an integer
}
foreach ($graph as $a => $b) {
//searches the vertexes that are pointed to for $a
if (!in_array($a,$graph)) {
echo $a;
for ($next = $b; isset($graph[$next]); $next = $graph[$next]) {
echo "->$next";
}
//because the loop doesn''t run one last time, like in the golfed version
echo "->$next/n";
}
}
Pitón
120 caracteres
Me gusta lo fácil que se lee en Python:
import sys
d=dict(map(str.split,sys.stdin))
for e in set(d)-set(d.values()):
while e in d:print e,''->'',;e=d[e]
print e
Y el resultado de correr sobre la muestra de pasta-bin:
784 -> 955 -> 381 -> 231 -> 76 -> 644 -> 380 -> 861 -> 522 -> 775 -> 565 -> 773 -> 188 -> 531 -> 219 -> 755 -> 247 -> 92 -> 723 -> 726 -> 606
821 -> 238 -> 745 -> 504 -> 99 -> 368 -> 412 -> 142 -> 921 -> 468 -> 315 -> 193 -> 674 -> 793 -> 673 -> 405 -> 185 -> 257 -> 21 -> 212 -> 783 -> 481 -> 269
477 -> 4 -> 470 -> 350 -> 401 -> 195 -> 258 -> 942 -> 263 -> 90 -> 716 -> 514 -> 110 -> 859 -> 976 -> 104 -> 119 -> 592 -> 968 -> 833 -> 731 -> 489 -> 364 -> 847 -> 727
C89 - 212 204 caracteres
#define M 1001
int t[M],r[M],a,b;main(){while(scanf("%d%d",&a,&b)>0)t[a+1]=r[a+1]=b+1;
for(a=1;a<M;a++)r[t[a]]=0;for(a=1;a<M;a++)if(r[a]){printf("%d",a-1);
for(b=t[a];b;b=t[b])printf("->%d",b-1);puts("");}}
No se cuentan las nuevas líneas innecesarias.
Mando:
$ wget -O - http://pastebin.com/download.php?i=R2PDGb2w | ./unique-paths
Salida:
477->4->470->350->401->195->258->942->263->90->716->514->110->859->976->104->119->592->968->833->731->489->364->847->727
784->955->381->231->76->644->380->861->522->775->565->773->188->531->219->755->247->92->723->726->606
821->238->745->504->99->368->412->142->921->468->315->193->674->793->673->405->185->257->21->212->783->481->269
Versión bonita:
#include <stdio.h>
int main(void)
{
/* Note: {0} initializes all items to zero. */
int target[1001] = {0}; /* If a → b, then target[a+1] == b+1. */
int root[1001] = {0}; /* If a is a root, then root[a+1] != 0. */
int a, b, i, next;
/* Read input numbers, setting the target of each node.
Also, mark each source node as a root. */
while (scanf("%d %d", &a, &b) == 2)
target[a+1] = root[a+1] = b+1;
/* Mark each node that is pointed to as not a root. */
for (i = 1; i <= 1000; i++)
root[target[i]] = 0;
/* For each root node, print its chain. */
for (i = 1; i <= 1000; i++) {
if (root[i] != 0) {
printf("%d", i-1);
for (next = target[i]; next != 0; next = target[next])
printf("->%d", next-1);
printf("/n");
}
}
return 0;
}
Haskell - 174 142 137 133 caracteres
import List
a#m=maybe[](/x->"->"++x++x#m)$lookup a m
q[f,s]=f//s>>=(/a->a++a#zip f s++"/n")
main=interact$q.transpose.map words.lines
Ungolfed
import Data.List
type Node = String
follow :: Node -> [(Node,Node)] -> String
follow node pairs = maybe "" step $ lookup node pairs
where step next = "->" ++ next ++ follow next pairs
chains :: [[Node]] -> String
chains [firsts,seconds] = concatMap chain $ firsts // seconds
where chain node = node ++ follow node pairs ++ "/n"
pairs = zip firsts seconds
process :: [String] -> String
process = chains . transpose . map words
main :: IO ()
main=interact $ process . lines
Enfoque menos elegante que antes, pero más corto! Inspirado por la idea de Nas Banov de h.keys-h.values
Ruby - 132 125 87
h=Hash[a=[*$<].map(&:split)]
1000.times{a.map!{|i|i+[h[i[-1]]]-[nil]}}
puts a.sort_by{|i|-i.size}.uniq(&:last).map{|i|i*''->''}
Tomó la idea de h.keys-h.values
Nas Banov:
h=Hash[[*$<].map &:split]
puts (h.keys-h.values).map{|i|s=i
s+=''->''+i=h[i]while h[i];s}
Aunque no es la respuesta, el siguiente script de Linux dibuja un gráfico del archivo de entrada:
cat FILE | (echo "digraph G {"; awk ''{print "/t" $1 "-> " $2;}''; echo "}") /
| dot -Tpng > out.png && eog out.png
Necesitará Graphviz instalado para el comando dot
, y eog
es el visor de imágenes de GNOME .
Ejecutar en el archivo de entrada, el gráfico se ve así:
Como puede ver, el gráfico de entrada es solo una colección de listas enlazadas individualmente sin nodos compartidos ni ciclos.
Lua, 166 bytes
Ow sí, finalmente un codegolf donde Lua no apesta. Producto adicional: funciona en cualquier cosa que esté separada por espacios (números de cualquier tamaño, cadenas, ...)
La versión sin golf:
-- Read in a file from stdout filled with pairs of numbers representing nodes of a (single-)directed graph.
-- x y means x->y (but not y->x)
g={}t={}w=io.write
i=io.read"*a" -- read in numbers from stdin
for x,y in i:gmatch"(%w+) (%w+)" do -- parse pairs
t[y]=1 -- add y to destinations (which never can be a starting point)
g[x]=y
end
for k,v in pairs(g) do -- go through all links
if not t[k] then -- only start on starting points
w(k) -- write the startingpoint
while v do -- as long as there is a destination ...
w(''->'',v) -- write link
v=g[v] -- next destination
end
w''/n''
end
end
La versión de golf:
g={}t={}w=io.write for x,y in io.read"*a":gmatch"(%w+) (%w+)"do t[y]=1 g[x]=y end for k,v in pairs(g)do if not t[k]then w(k)while v do w(''->'',v)v=g[v]end w''/n''end end
Java
372 337 304 bytes
Actualización :
- Genéricos removidos. Y al parecer, la clase puede prescindir de ser "público" (Thnx Sean)
- Clase eliminada, reemplazado por Enum. (Ver comentarios, Thnx Nabb)
import java.util.*;enum M{M;{Scanner s=new Scanner(System.in);final Map g=new HashMap();while(s.hasNext()){g.put(s.nextInt(),s.nextInt());}for(int a:new HashSet<Integer>(g.keySet()){{removeAll(g.values());}}){while(g.containsKey(a)){System.out.print(a+"->");a=(Integer)g.get(a);}System.out.println(a);}}}