Reputation: 133
I'm trying to modify a list of lists with certain conditions, if a nested list contains x, I'd like to remove that list from the list, if a nested list contains -x, I'd like to remove -x from that list while still keeping the said list. Finally, if the nested list doesn't contain x or -x, I'd keep it.
So far this is what I've tried, I don't really get why it doesn't work as intented...
let rec simplify i clauses =
match clauses with
| [] -> []
| x::y ->
if (List.mem i x) then
[] @ simplify i y
else if (List.mem (-i) x) then
List.filter (fun x -> x != -i) x @ simplify i y
else
[x];;
The expected results would be that:
simplify (-1) [[-1;2];[-1;7];[-2;1];[-2;3];[-3;2];[-3;4];[-4;5];[-4;15];[-5;2];[-5;4];[-6;5];[-7;1];[-7;8];[-7;6];[-8;7];[-8;9];[-8;10];[-9;8];[-10;8];[-10;11];[-10;12];[-11;9];[-11;10];[-12;6];[-12;10];[-12;13];[-12;15];[-13;11];[-14;13];[-14;15];[-15;12];[1];[-14]]
;;
- : int list list =
[[-14]; []; [-15; 12]; [-14; 15]; [-14; 13]; [-13; 11]; [-12; 15]; [-12; 13];
[-12; 10]; [-12; 6]; [-11; 10]; [-11; 9]; [-10; 12]; [-10; 11]; [-10; 8];
[-9; 8]; [-8; 10]; [-8; 9]; [-8; 7]; [-7; 6]; [-7; 8]; [-7]; [-6; 5];
[-5; 4]; [-5; 2]; [-4; 15]; [-4; 5]; [-3; 4]; [-3; 2]; [-2; 3]; [-2]]
Whereas the actual results are:
simplifie_aux (-1) [[-1;2];[-1;7];[-2;1];[-2;3];[-3;2];[-3;4];[-4;5];[-4;15];[-5;2];[-5;4];[-6;5];[-7;1];[-7;8];[-7;6];[-8;7];[-8;9];[-8;10];[-9;8];[-10;8];[-10;11];[-10;12];[-11;9];[-11;10];[-12;6];[-12;10];[-12;13];[-12;15];[-13;11];[-14;13];[-14;15];[-15;12];[1];[-14]]
;;
- : int list list = [[-2]; [-2; 3]]
Thanks.
Upvotes: 0
Views: 73
Reputation: 36620
This seems like an ideal place to utilize List.filter_map
as you are trying to perform both filtering and mapping at the same time.
# [[-1; 2]; [-1; 7]; [-2; 1]; [-2; 3]; [-3; 2]; [-3; 4];
[-4; 5]; [-4; 15]; [-5; 2]; [-5; 4]; [-6; 5]; [-7; 1];
[-7; 8]; [-7; 6]; [-8; 7]; [-8; 9]; [-8; 10]; [-9; 8];
[-10; 8]; [-10; 11]; [-10; 12]; [-11; 9]; [-11; 10];
[-12; 6]; [-12; 10]; [-12; 13]; [-12; 15]; [-13; 11];
[-14; 13]; [-14; 15]; [-15; 12]; [1]; [-14]]
|> List.filter_map (fun lst ->
if List.mem ~-1 lst then None
else if List.mem 1 lst then Some (List.filter ((<>) 1) lst)
else Some lst
);;
- : int list list =
[[-2]; [-2; 3]; [-3; 2]; [-3; 4]; [-4; 5]; [-4; 15]; [-5; 2]; [-5; 4];
[-6; 5]; [-7]; [-7; 8]; [-7; 6]; [-8; 7]; [-8; 9]; [-8; 10]; [-9; 8];
[-10; 8]; [-10; 11]; [-10; 12]; [-11; 9]; [-11; 10]; [-12; 6]; [-12; 10];
[-12; 13]; [-12; 15]; [-13; 11]; [-14; 13]; [-14; 15]; [-15; 12]; [];
[-14]]
Upvotes: 0
Reputation: 32446
In your code, it appears you should be recursing in the final else [x]
case as well. I would rewrite it as a fold
, however, since you are dropping (some) empty lists from your expected output, eg.
let simplify i clauses =
let f acc lst =
if List.mem i lst then acc
else [List.filter (fun x -> x != -i) lst] @ acc
in List.fold_left f [] clauses
(* - : int list list =
[[-14]; []; [-15; 12]; [-14; 15]; ... ] *)
Upvotes: 0