Ocaml programowanie funkcyjne zadanie

0

Mam problem z następującym zadaniem:
Napisz funkcję rozdzielającą listę wejściową na trzy podlisty:

  • W pierwszej podliście mają znajdować się wszystkie elementy podzielne przez 10.
  • W drugiej podliście mają znajdować się wszystkie elementy podzielne przez 5.
  • W trzeciej podliście mają znajdować się wszystkie pozostałe elementy.

Porządek elementów musi być zachowany. Wynik zwróć w postaci trójki list.

Przykład:

  • wywołanie: natrzy [20;21;25;30;40];;
  • wynik: ([20;30;40],[20;25;30;40],[21])

Jak na razie mam coś takiego:

let rec natrzy list ={
	if list=[] then []
	else if List.hd list mod 10 = 0 then natrzy @ List.tl list
	else if List.hd list mod 5 = 0 then natrzy @ List.tl list
	else list
}

Wydaje mi się, że warunek mam dobry tylko nie wiem jak połączyć wybrany element z nowo powstała listą (nie wiem czy to ma sens co napisałem w programie...).

Pozdrawiam

4

Ostatni raz w ocamlu pisałem 100 lat temu, ale łamigłówka zawsze w cenie ;)

let rec natrzy l = 
	match l with
	| [] -> ([],[],[])
	| head :: tail -> 
		if head mod 10 = 0 then  
			match (natrzy tail) with 
				(ten, five, rest) -> (head :: ten, head :: five, rest)
		else if head mod 5 = 0 then 
			match (natrzy tail) 
				with (ten, five, rest) -> (ten, head :: five, rest)
		else 
			match (natrzy tail) 
				with (ten, five, rest) -> (ten, five, head :: rest)
;;
natrzy [20;21;25;30;40];;

//
- : int list * int list * int list = ([20; 30; 40], [20; 25; 30; 40], [21])

I nie, to co tam wyżej napisałeś nie ma najmniejszego sensu.

Może znajdzie sie tu jakiś wprawniejszy ocamlowiec albo haskellowiec i napisze bardziej funkcyjnie ;) @Wibowit @winerfresh czy kto tam jeszcze coś funkcyjnie pisze ;)

3
let split ts =
  let rec split' (a0, a5, a10) xs =
    match xs with
    | [] -> (List.rev a0, List.rev a5, List.rev a10)
    | x::xss ->
      if x mod 10 = 0 then split' (a0, x::a5, x::a10) xss
      else if x mod 5 = 0 then split' (a0, x::a5, a10) xss
      else split' (x::a0, a5, a10) xss
  in
    split' ([], [], []) ts
;;
5
let f xs = 
	let fs, rs = List.partition (fun x -> x mod  5 == 0) xs in
	let ts     = List.filter    (fun x -> x mod 10 == 0) fs in
	(ts, fs, rs);;
0

Dziękuję bardzo za szybką odpowiedz :) Macie pomysł jak połączyć listy żeby był element z jednej listy, np. wywołanie: polacz [5;4;3;2] [1;2;3;4;5;6];; wynik: [5;1;4;2;3;3;2;4;5;6], następnie element z drugiej listy itd.?

Mam coś takiego :

let rec polacz listOfLists=
	if listOfLists=[]then[]
	else List.hd listOfLists@polacz(List.tl listOfLists);;

ale to łączy listy, najpierw jedna później druga po prostu

1

No no, całej pracy domowej to za ciebie nie będziemy odrabiać. Ja bym uzył pattern matchingu i odciął od wejściowych list "głowy" i appendował do nowej listy, a potem do tego appendował rekurencyjne wywołanie twojej funkcji na krotce złozonej z "ogonów" wejściowych list.

0

ok dzięki wielkie jeszcze raz

0
Shalom napisał(a):

do tego appendował rekurencyjne wywołanie twojej funkcji na krotce złozonej z "ogonów" wejściowych list.

Pamiętaj tylko o rekurencji ogonowej, powinieneś przekazywać to w akumulatorze.

0

znacie może jakieś dobre tutoriala do Ocamla ? bo mimo tego że znam algorytm, to nie umiem tego napisać. Już z 3-4h siedzę nad tak prostym zadaniem i nic z tego nie wynika, a chciałbym się nauczyć programować w tym języku. Nie chodzi mi nawet o suche rozwiązanie tylko żebym załapał programowanie funkcyjne albo chociaż podstawy bo to aktualnie mam to na studiach ...

1

http://learnyouahaskell.com/chapters
Wprawdzie do Haskella, ale nauczy Cię myślenia funkcyjnego, reszta to już kwestia składni.

1 użytkowników online, w tym zalogowanych: 0, gości: 1