Julia Language
mientras bucles
Buscar..
Sintaxis
- mientras cond cuerpo; fin
- descanso
- continuar
Observaciones
El while
de bucle no tiene un valor; aunque se puede usar en la posición de expresión, su tipo es Void
y el valor obtenido no será nothing
.
Secuencia de collatz
El while
bucle se ejecuta su cuerpo, siempre y cuando la condición se cumple. Por ejemplo, el siguiente código calcula e imprime la secuencia de Collatz desde un número dado:
function collatz(n)
while n ≠ 1
println(n)
n = iseven(n) ? n ÷ 2 : 3n + 1
end
println("1... and 4, 2, 1, 4, 2, 1 and so on")
end
Uso:
julia> collatz(10)
10
5
16
8
4
2
1... and 4, 2, 1, 4, 2, 1 and so on
Es posible escribir cualquier bucle de forma recursiva, y para complejos while
bucles, a veces la variante recursiva es más clara. Sin embargo, en Julia, los bucles tienen algunas ventajas distintas sobre la recursión:
- Julia no garantiza la eliminación de la llamada de cola, por lo que la recursión usa memoria adicional y puede causar errores de desbordamiento de pila.
- Y además, por la misma razón, un bucle puede tener una sobrecarga reducida y correr más rápido.
Ejecutar una vez antes de probar la condición
A veces, uno quiere ejecutar algún código de inicialización una vez antes de probar una condición. En algunos otros idiomas, este tipo de bucle tiene una sintaxis especial de do
- while
. Sin embargo, esta sintaxis se puede sustituir por un habitual while
bucle y break
declaración, por lo que Julia no se han especializado do
- while
la sintaxis. En su lugar, uno escribe:
local name
# continue asking for input until satisfied
while true
# read user input
println("Type your name, without lowercase letters:")
name = readline()
# if there are no lowercase letters, we have our result!
!any(islower, name) && break
end
Tenga en cuenta que en algunas situaciones, tales bucles podrían ser más claros con la recursión:
function getname()
println("Type your name, without lowercase letters:")
name = readline()
if any(islower, name)
getname() # this name is unacceptable; try again
else
name # this name is good, return it
end
end
Búsqueda de amplitud
(Aunque este ejemplo está escrito utilizando la sintaxis introducida en la versión v0.5, también puede funcionar con algunas modificaciones en versiones anteriores).
Esta aplicación de búsqueda en anchura (BFS) en un gráfico representado con listas de adyacencia utiliza while
bucles y el return
comunicado. La tarea que resolveremos es la siguiente: tenemos una secuencia de personas y una secuencia de amistades (las amistades son mutuas). Queremos determinar el grado de conexión entre dos personas. Es decir, si dos personas son amigas, devolveremos 1
; si uno es amigo de un amigo del otro, regresaremos 2
, y así sucesivamente.
Primero, supongamos que ya tenemos una lista de adyacencia: un Dict
mapeo T
a Array{T, 1}
, donde las claves son personas y los valores son todos los amigos de esa persona. Aquí podemos representar a personas con cualquier tipo de T
que escojamos; En este ejemplo, usaremos Symbol
. En el algoritmo BFS, mantenemos una cola de personas para "visitar", y marcamos su distancia desde el nodo de origen.
function degree(adjlist, source, dest)
distances = Dict(source => 0)
queue = [source]
# until the queue is empty, get elements and inspect their neighbours
while !isempty(queue)
# shift the first element off the queue
current = shift!(queue)
# base case: if this is the destination, just return the distance
if current == dest
return distances[dest]
end
# go through all the neighbours
for neighbour in adjlist[current]
# if their distance is not already known...
if !haskey(distances, neighbour)
# then set the distance
distances[neighbour] = distances[current] + 1
# and put into queue for later inspection
push!(queue, neighbour)
end
end
end
# we could not find a valid path
error("$source and $dest are not connected.")
end
Ahora, escribiremos una función para construir una lista de adyacencia dada una secuencia de personas y una secuencia de tuplas (person, person)
:
function makeadjlist(people, friendships)
# dictionary comprehension (with generator expression)
result = Dict(p => eltype(people)[] for p in people)
# deconstructing for; friendship is mutual
for (a, b) in friendships
push!(result[a], b)
push!(result[b], a)
end
result
end
Ahora podemos definir la función original:
degree(people, friendships, source, dest) =
degree(makeadjlist(people, friendships), source, dest)
Ahora probemos nuestra función en algunos datos.
const people = [:jean, :javert, :cosette, :gavroche, :éponine, :marius]
const friendships = [
(:jean, :cosette),
(:jean, :marius),
(:cosette, :éponine),
(:cosette, :marius),
(:gavroche, :éponine)
]
Jean está conectado a sí mismo en 0
pasos:
julia> degree(people, friendships, :jean, :jean)
0
Jean y Cosette son amigos, y por eso tienen el grado 1
:
julia> degree(people, friendships, :jean, :cosette)
1
Jean y Gavroche están conectados indirectamente a través de Cosette y luego a Marius, por lo que su grado es 3
:
julia> degree(people, friendships, :jean, :gavroche)
3
Javert y Marius no están conectados a través de ninguna cadena, por lo que se produce un error:
julia> degree(people, friendships, :javert, :marius)
ERROR: javert and marius are not connected.
in degree(::Dict{Symbol,Array{Symbol,1}}, ::Symbol, ::Symbol) at ./REPL[28]:27
in degree(::Array{Symbol,1}, ::Array{Tuple{Symbol,Symbol},1}, ::Symbol, ::Symbol) at ./REPL[30]:1