新手關於julia的基本問題


#1

各位前輩好 我剛學julia大約一個多月 目前還在讀文檔階段 但是對於一個題目實在忍不住好奇 想請各位前輩指點
題目是程式初學者常見的傳教士與食人族渡河 我的問題如下 :

  1. 如果我想把兩者人數在事後以輸入的方式來自由決定 請問在julia中 該如何寫?
  2. 輸入完人數後 會形成一組最初的數組 (m , c , l) m是傳教士數量 c是食人族數量 l 是船的位置 加上船的運載量假設是2 可能運載方式有(2,0) , (1,1), (0,2) 三種 於是我需要把最初數組 與這三種可能運載方式形成的陣列的每個去運算 把符合條件的結果放到另一個新的陣列中 再做下一次運算 我的問題是
    a. 我的思考方式是對的嗎?
    假若是對的
    b. 如何建立一個陣列 是由數組組成?
    c. 如何讓數組去跟陣列中每個數組去做運算?
    d. 運算之後 符合條件的結果 其數量會隨初始條件變化 該如何建立一個有彈性的陣列去放計算結果?
    以上是我的疑惑 請各位前輩有空能指導我 謝謝大家

#2

也就是 “交互式的输入/从命令行读取”

最简单的就是用 readline, 详细的参数见help:?readline。再加个 println 就能实现简单的交互

julia> println("input number of people: [n,m]")
input number of people: [n,m]

julia> ipt = readline(stdin)
5,6
"5,6"

julia> split(ipt, ',')
2-element Array{SubString{String},1}:
 "5"
 "6"

或者你想要更稍微复杂一点的类 REPL 形式的交互见:


涉及到具体的问题的就先不说了,我先回答下其他问题。而且以 “傳教士 食人族 渡河” 为关键词再 google 上能搜到繁体中文/简体中文的具体算法分析讲解文章不少。英文关键词应该是 Missionaries and cannibals problem - Wikipedia


就是建立一个数组的数组嘛,Julia 里就是 Array 从 1~n 维都可以,并且可以嵌套。

这里就简单演示下如何构建数组的数组

julia> res = []
0-element Array{Any,1}

julia> for _ in 1:10
           m, c, l = rand(1:10), rand(1:10), rand(0:1)
           push!(res, [m, c, l])
       end

julia> res
10-element Array{Any,1}:
 [2, 8, 0]
 [3, 7, 1]
 [5, 7, 0]
 [8, 10, 0]
 [10, 9, 1]
 [4, 6, 1]
 [9, 3, 0]
 [7, 2, 0]
 [2, 8, 0]
 [7, 3, 1]

关于多维数组的操作:
https://docs.juliacn.com/latest/manual/arrays/


你有一个数组的数组,对最外层数组循环就行了。还要从另一个数组中拿东西,就再加一层循环。

julia> boat_case = [(2,0) , (1,1), (0,2)]
3-element Array{Tuple{Int64,Int64},1}:
 (2, 0)
 (1, 1)
 (0, 2)

julia> for (i, j) in boat_case
           # do sth
           println("(i, j)=", (i, j))
           for (m, c, l) in res # 使用的是上一部分中的 res 变量
               # do sth
               println("(m, c, l)=", (m, c, l))
           end
       end
(i, j)=(2, 0)
(m, c, l)=(2, 8, 0)
(m, c, l)=(3, 7, 1)
(m, c, l)=(5, 7, 0)
(m, c, l)=(8, 10, 0)
(m, c, l)=(10, 9, 1)
(m, c, l)=(4, 6, 1)
(m, c, l)=(9, 3, 0)
(m, c, l)=(7, 2, 0)
(m, c, l)=(2, 8, 0)
(m, c, l)=(7, 3, 1)
(i, j)=(1, 1)
(m, c, l)=(2, 8, 0)
(m, c, l)=(3, 7, 1)
(m, c, l)=(5, 7, 0)
(m, c, l)=(8, 10, 0)
(m, c, l)=(10, 9, 1)
(m, c, l)=(4, 6, 1)
(m, c, l)=(9, 3, 0)
(m, c, l)=(7, 2, 0)
(m, c, l)=(2, 8, 0)
(m, c, l)=(7, 3, 1)
(i, j)=(0, 2)
(m, c, l)=(2, 8, 0)
(m, c, l)=(3, 7, 1)
(m, c, l)=(5, 7, 0)
(m, c, l)=(8, 10, 0)
(m, c, l)=(10, 9, 1)
(m, c, l)=(4, 6, 1)
(m, c, l)=(9, 3, 0)
(m, c, l)=(7, 2, 0)
(m, c, l)=(2, 8, 0)
(m, c, l)=(7, 3, 1)

参见 “b. ” 的回答,向一个空数组中 push! 东西就行了,没有长度限制,可以不初始化。


#3

找了个繁体中文讲解的视频,虽然是用的 C++ 不过听算法思路就行了。

还有一个用线性代数的方法计算的文章


#4

謝謝前輩 經過您的說明 我對數組以及陣列有更多了解 也就是將(x,y)數組 用push! 或 append!方式 放到 [ ] 陣列中 同時我也會去閱讀您提供的一些鏈結 做更多了解 謝謝您花時間來指導我 感謝


#5

您好
我另外試了以下代碼
println(“輸入傳教士人數”)
m=readline(stdin)
println(“輸入食人族人數”)
c=readline(stdin)
println(“傳教士"(m)"人" "食人族"©"人”)
但是跑不出來 請教發生了什麼錯誤?


#6

我这边改了中英文引号后没有问题。

julia> println(“輸入傳教士人數”)
ERROR: syntax: invalid character "“" near column 10

julia> println("輸入傳教士人數")
輸入傳教士人數

julia> m=readline(stdin) 
1
"1"

有报错吗?有问题无比附上报错信息。

另外 readline 那一句输入完后,按回车执行,会另起一行等待你的输入。像我上面就输入 1,然后再按回车, m 就得到字符串 "1"


#7

您好 我附上截圖給您看 我不是在REPL中直接執行 在我執行整段程式時 會出現要求輸入人數的輸出 但是當我輸入數字後 就當住了 完全沒有回應 不知道是哪裡出錯? 請求協助 謝謝


#8

catch 在这里是干什么的?
针对上述代码,我觉得存在的问题是:

  1. catch删掉;
  2. 你的m和c是字符串,你需要用parse(Int, m)将其转化成number,才能进行后续的比较
  3. 感觉REPL(如果你直接粘贴含stdin的代码,应该不会正常运行)或者Atom对stdin支持不好,建议你直接在Atom的repl中键入include(“XXX.jl”)运行文件,而不是采用Run block or Run file under Julia menu ,应该会按照预想的运行
  4. 字符串中的插入符$不要好用""将其框住

最后建议你还是再看看说明书中关于string章节。:grinning:


#9

您好
首先感謝您的建議 我按照您的說法 把代碼改成下 :
println(“輸入傳教士人數”)
m=readline(stdin)
parse(m,Int)
println(“輸入食人族人數”)
c=readline(stdin)
parse(c,Int)
println(“傳教士” (m) "人" "食人族" © “人”)
if
m>=c
println(“傳教士安全”)
else
println(“注意傳教士安全”)
end
在REPL執行 include(“practice1.0.ji”) # 代碼所在位置
執行結果如下 :
julia> include(“practice1.0.ji”)
ERROR: could not open file C:\Users\rex\Desktop\julia notebook\practice1.0.ji
Stacktrace:
[1] include at .\boot.jl:317 [inlined]
[2] include_relative(::Module, ::String) at .\loading.jl:1044
[3] include(::Module, ::String) at .\sysimg.jl:29
[4] include(::String) at .\client.jl:392
[5] top-level scope at none:0
請問我是否有那裡沒有弄清楚? 請您再指教 感謝


#10
println("輸入傳教士人數")
m=readline(stdin)
m2num = parse(Int, m)
println("輸入食人族人數")
c=readline(stdin)
c2num = parse(Int, c)
println("傳教士$(m2num)人,  食人族$(c2num)人")
if m2num > c2num
    println("傳教士安全")
else
    println("注意傳教士安全")
end

  1. 请注意英文双引号的使用,不知道是不是拷贝的问题
  2. include文件注意文件所在的目录,你可以看看上面的错误提示,他是在工作目录上搜索这个文件,不过没找到这个文件。因此:建议(1)当你不会设置工作目录时,可给出文件的绝对路径;注意输入目录时,用\\或者/做为文件夹的分隔符;(2)似乎你的文件名没有.jl的后缀,注意审核并添加。

#11

@ shilu1984 感謝您的協助 希望以後能多跟各位討教 再次感謝