/ / Kod nie działa: sortowanie tablic w ocaml - tablice, sortowanie, ocaml

Kod nie działa: sortowanie tablic w ocaml - tablice, sortowanie, ocaml

Jestem nowy w Ocaml i mam z tym problemkod (poniżej). Próbuję napisać program do sortowania tablicy. Podzieliłem tablicę na dwie połówki, a następnie użyłem Array.sort na tych dwóch tablicach (naprawię to później, więc nie użyję Array.sort). A potem chciałem porównać elementy z tych dwóch tablic, ale mój kod nie działa. Czy ktoś może mi powiedzieć, gdzie jest problem?

let a =[|5;4;2;6;1;3|] ;;
let n = Array.length a;;


let l= Array.sub a 0 (n/2);;
Array.sort compare l;;
l;;
let ll= Array.length l;;


let r= Array.sub a (n/2) (n/2);;
Array.sort compare r;;
r;;
let lr=Array.length r;;

let merge l r a =
let k =ref 0 in
let i = ref 0 in
let j =ref 0 in

while( !i<ll && !j< lr) do
if(l.(!i) <= r.(!j)) then
a.(!k) <- l.(!i)
i:= !i+1
else begin
a.(!k) <- r.(!j)
j:= !j+1;
k:= !k+1
end;

while (!i<ll) do
a.(!k)<-l.(!i)
i:= !i+1;
k:=!k+1;
done;

while (!j<ll) do
a.(!k) <-r.(!j)
j:= !j+1;
k:= !k+1
done;
done;;

merge l r a;;

Odpowiedzi:

1 dla odpowiedzi № 1

Twój problem wynika z niezrozumienia instrukcji. Spróbujmy wyjaśnić to w łatwy i krótki sposób:

  • Jeśli wyrażenie zwraca wartość, jest to wyrażenie (a bool, an int, a function ...)
  • Jeśli nie zwraca wartości (co oznacza efekt uboczny), jest instrukcją (i mówimy, że zwraca unit ponieważ tak naprawdę to właśnie robi).

Kiedy masz sekwencję (tak nazywa się wykonywanie wielu instrukcji jeden po drugim), rozdzielasz je za pomocą a ;.

Na przykład, jeśli to napiszę

let f x = x := 1; print_int !x; print_newline ()

Mam sekwencję i muszę oddzielić moje instrukcje ;.

Gdybym napisał:

let f x = x := 1 print_int !x print_newline ()

Łatwo zrozumieć, że OCaml nie wie, gdzie instrukcje są oddzielone (jest to x := 1 print_int; !x? Czy cokolwiek innego?) Dlatego właśnie tego potrzebujesz ;.

Teraz pojawia się problem if.

Jeśli piszesz

 if cond then instr1; instr2

To, co jest analizowane, jest

 (if cond then instr1); instr2

Tak, if cond then instr1 jest instrukcją, ponieważ, cóż, wraca unitnie? Więc instr2 nie jest w twoim then blok.

Ale jeśli napiszesz

 if cond then let e1 = e2 in instr1; instr2

Następnie instr2 jest w then blok, ponieważ konstrukcja let ... in tworzy blok, w którym wszystkie instrukcje są zagnieżdżone.

Jeśli zaczynasz z OCaml, moja cenna rada byłaby następująca: zawsze piszbegin ... end w twoich warunkach. Zapewnisz, że to, co piszesz, jest tym, o czym myślisz, że jest parsowane.


1 dla odpowiedzi nr 2

Jestem zbyt nowy, by komentować, ale wskażę, że każdy blok potrzebuje albo nawiasów () lub begin ... end. Tak więc, twoja pierwsza if oświadczenie powinno mieć then begin na końcu linii. Oświadczenia między begin i else potrzebujemy średników, aby je rozdzielić, jak w:

if(l.(!i) <= r.(!j)) then begin
a.(!k) <- l.(!i);
i:= !i+1
end else begin
a.(!k) <- r.(!j);
j := !j+1;
k:= !k+1
end;

Potrzebne są również pierwsze dwie linie pętli whilesemi-colons, ponieważ są one również blokiem instrukcji. Zauważ, że nie potrzebujesz średnika dla ostatniej instrukcji w bloku. Są separatorami, a nie końcem instrukcji. Ponadto, jako skrót, możesz użyć incr i dla i := !i + 1 i podobne stwierdzenia. Nigdy nie używaj l ani ll jako nazw zmiennych. :-)