У меня есть следующая функция
let update s =
for i=0 to ((Array.length s) - 2) do
for j=0 to (Array.length (s.(i))) - 2 do
(s.(i)).(j) <- (s.(i).(j)) + 1;
done;
done
и кажется, что соответствующие координаты 2D-массива s
увеличиваются на 2 при каждом вызове.
Ниже приведен полный код на случай, если будет полезно увидеть, как я использую эти вещи.
бэкэнд.мл
type sim = int array array
let create m n = Array.make m (Array.make n 0)
let update s =
for i=0 to ((Array.length s) - 2) do
for j=0 to (Array.length (s.(i))) - 2 do
(s.(i)).(j) <- (s.(i).(j)) + 2;
done;
done
let toString s =
let rows = Array.length s in
if rows = 0 then "--\n||\n--"
else
let cols = Array.length s.(0) in
let st = ref "--\n" in
for i=0 to rows-1 do
for j=0 to cols-1 do
st := !st ^ (string_of_int s.(i).(j)) ^ ","
done;
st := !st ^ "\n"
done;
!st
main.ml
open Test.Backend
let sim = create
(int_of_string Sys.argv.(1))
(int_of_string Sys.argv.(2))
;;
while true do
print_endline (toString sim);
update sim;
Unix.sleepf 1.;
done
Распечатка запуска с аргументами командной строки 3 и 10 выглядит следующим образом.
--
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
--
2,2,2,2,2,2,2,2,2,0,
2,2,2,2,2,2,2,2,2,0,
2,2,2,2,2,2,2,2,2,0,
--
4,4,4,4,4,4,4,4,4,0,
4,4,4,4,4,4,4,4,4,0,
4,4,4,4,4,4,4,4,4,0,
Я даже не могу предположить, почему он это делает. Я расставил скобки, подправил несколько чисел, просто чтобы посмотреть, изменит ли это что-нибудь. Я также не понимаю, почему это когда-либо обновляет последнюю строку, поскольку я пытался вычесть «слишком много». Я предполагаю, что это как-то связано с проблемой слишком большого количества добавлений. Но когда я пытаюсь логически это проанализировать, я просто не могу понять, как это происходит.
Поработав, я добавил строку печати в функцию обновления и обнаружил, что функция обновления вызывается дважды за каждый раз, когда выполняется цикл while. Вот теперь я не понимаю, почему так происходит, но это прогресс!
Ваша проблема заключается здесь:
let create m n = Array.make m (Array.make n 0)
Вы создали массив со ссылками m
на тот же массив с нулями n
, потому что Array.make n 0
вызывается только один раз.
Учитывать:
# let m = Array.make 2 (Array.make 2 2);;
val m : int array array = [|[|2; 2|]; [|2; 2|]|]
# m.(0).(0) <- 8;;
- : unit = ()
# m;;
- : int array array = [|[|8; 2|]; [|8; 2|]|]
Вероятно, вы захотите использовать Array.make_matrix.
# let m = Array.make_matrix 2 2 2;;
val m : int array array = [|[|2; 2|]; [|2; 2|]|]
# m.(0).(0) <- 8;;
- : unit = ()
# m;;
- : int array array = [|[|8; 2|]; [|2; 2|]|]
Вы также можете использовать Array.init, чтобы убедиться, что у вас есть массив уникальных массивов.
# let m = Array.init 2 (fun _ -> Array.make 2 2);;
val m : int array array = [|[|2; 2|]; [|2; 2|]|]
# m.(0).(0) <- 8;;
- : unit = ()
# m;;
- : int array array = [|[|8; 2|]; [|2; 2|]|]
В качестве дополнительного предложения вы можете использовать модуль Buffer при создании строки для вывода.
let toString s =
let rows = Array.length s in
if rows = 0 then "--\n||\n--"
else
let buf = Buffer.create 16 in
let cols = Array.length s.(0) in
Buffer.add_string buf "--\n";
for i=0 to rows-1 do
for j=0 to cols-1 do
Buffer.add_string buf @@ string_of_int s.(i).(j);
Buffer.add_string buf ","
done;
Buffer.add_string buf "\n"
done;
Buffer.contents buf
Было бы неплохо создать собственную функцию форматирования, как показано ниже. Это гораздо более гибко, но логика следует тому, что вы уже создали.
# let sim_pp fmt s =
let rows = Array.length s in
if rows = 0 then
Format.fprintf fmt "--\n||\n--"
else (
let cols = Array.length s.(0) in
Format.fprintf fmt "--\n";
for i = 0 to rows - 1 do
for j = 0 to cols - 1 do
Format.fprintf fmt "%d," s.(i).(j)
done;
Format.fprintf fmt "\n"
done
);;
val sim_pp : Format.formatter -> int array array -> unit = <fun>
# Format.printf "%a\n" sim_pp [|[|1; 2|]; [|3; 4|]|];;
--
1,2,
3,4,
- : unit = ()
# Format.asprintf "%a\n" sim_pp [|[|1; 2|]; [|3; 4|]|];;
- : string = "--\n1,2,\n3,4,\n\n"
# [|[|1; 2|]; [|3; 4|]|]
|> Format.asprintf "%a\n" sim_pp
|> print_string;;
--
1,2,
3,4,
- : unit = ()
Хороший обзор правил приоритета операторов покажет, что в следующих скобках гораздо больше скобок, чем необходимо.
type sim = int array array let create m n = Array.make m (Array.make n 0) let update s = for i=0 to ((Array.length s) - 2) do for j=0 to (Array.length (s.(i))) - 2 do (s.(i)).(j) <- (s.(i).(j)) + 2; done; done let toString s = let rows = Array.length s in if rows = 0 then "--\n||\n--" else let cols = Array.length s.(0) in let st = ref "--\n" in for i=0 to rows-1 do for j=0 to cols-1 do st := !st ^ (string_of_int s.(i).(j)) ^ "," done; st := !st ^ "\n" done; !st
Его можно сократить до:
type sim = int array array
let create m n =
Array.make m (Array.make n 0)
let update s =
for i=0 to Array.length s - 2 do
for j=0 to Array.length s.(i) - 2 do
s.(i).(j) <- s.(i).(j) + 2;
done;
done
let toString s =
let rows = Array.length s in
if rows = 0 then "--\n||\n--"
else
let cols = Array.length s.(0) in
let st = ref "--\n" in
for i=0 to rows-1 do
for j=0 to cols-1 do
st := !st ^ string_of_int s.(i).(j) ^ ","
done;
st := !st ^ "\n"
done;
!st