-1

I have 3 Constraints for a List:

  1. list ins 1..9
  2. all_different(list)
  3. lists in the list --> I get some lists from the list. every list from the list has to fulfill the constraint to be gapless. for example:

    List1 = [1,3,2,4];
    List2=[3,2,1];
    List3= [5,7,6]
    WRONG: List4=[1,4,3]

1 Question: You have an idea to set constraint 3? I would sort the lists and check for: Element1=Element2+1?

After all i want to use labeling([ff],list)

2 Question: I get a solution with labeling if i set contraint 3 like my idea?

Hans
  • 119
  • 1
  • 12
  • 5
    [MCVE](http://stackoverflow.com/help/mcve), please. Stick to programs, your words are hard to understand. – false Feb 12 '15 at 06:55
  • i will edit my question tomorrow. first i have to finish my bachelorthesis. Sry for the bad question. – Hans Feb 12 '15 at 07:31
  • Are all lists within the list a list of only one element? If so, it's not clear why they are lists. – lurker Feb 12 '15 at 11:27
  • absolute right lurker, it was a mistake that the elemets were lists – Hans Feb 12 '15 at 13:31

2 Answers2

2

I think this is along the lines of what you're looking for...

:- use_module(library(clpfd)).

foo(L) :-
    Len in 1..9,    % lists of length 1 through 9
    length(L, Len),
    L ins 1..9,
    label(L),
    msort(L, LS),
    series(LS).

series([_]).
series([X,Y|T]) :- Y #= X + 1, series([Y|T]).

Since you are already constraining the list to a specific series behavior, indicating all_different would be redundant.

Another approach could be:

foo(L) :-
    [Fst,Lst] ins 1..9,
    Fst #=< Lst,
    Len #= Lst - Fst + 1,
    length(L, Len),
    label([Fst,Lst]),
    L ins Fst..Lst,
    all_different(L),
    label(L).

These predicates generate all possible lists meeting the criteria, and should succeed if and only if the given list meets the criteria.

lurker
  • 53,004
  • 8
  • 60
  • 93
  • 1
    Regarding the first snippet: There is `in/2` and `indomain/1` for single finite domain variables. And: Replacing `=:=` by `#=` would make `series/2` more general. – mat Feb 12 '15 at 16:52
  • @mat yeah thanks. I'm not used to using SWI. I'll correct. Originally, I had `#=` but didn't think it mattered since the variables were already instantiated/labeled. But I agree with your comment. – lurker Feb 12 '15 at 16:55
  • 1
    with `indomain/1`, I mean you can replace `label([Len])` by `indomain(Len)` in both snippets. – mat Feb 12 '15 at 17:27
  • @mat ah OK, thanks. I wasn't familiar with `indomain/1` before. Is there an advantage besides not having to represent a single variable as a list as in `label/1`? – lurker Feb 12 '15 at 17:48
  • 1
    I find it a bit easier to read, because it immediately makes clear that only a single variable is involved. (The efficiency difference is completely negligible in my opinion.) – mat Feb 13 '15 at 16:16
  • the answer helped me a lot. BUT the problem is i want to solve [Str8ts](http://www.str8ts.com/). If i check the constraints for the rows first. all undefined variables will be defined after ill check with foo. then i want to check the columns of the puzzle. but foo will fail, cause i already defined the variables by foo all rows. is it possible to set the constraint without label it. and after i foo rows and columns, label all? – Hans Feb 18 '15 at 16:22
  • @Hans, ok your original question wasn't specifically formulated to handle all the conditions you're now describing. But, yes, you can defer the `label(L)`. The `label([Fst,Lst])` is needed for the following `ins` to work. – lurker Feb 18 '15 at 19:37
  • what do you mean by the following `ins` and `label([first,last])` – Hans Feb 18 '15 at 19:49
  • @Hans see the second predicate in my answer. – lurker Feb 18 '15 at 19:50
  • @lurker if i use labeling after i set the constraints for the rows, i get the error: `Arguments are not sufficiently instantiated` This means the domain for the variables is not set or? – Hans Feb 19 '15 at 09:24
  • @lurker this is my predicate for constraint 3 now: `foo(L) :- [Fst,Lst] ins 1..9, Fst #=< Lst, Len #= Lst - Fst + 1, length(L, Len), label([Fst,Lst]), L ins Fst..Lst, all_different(L).` – Hans Feb 19 '15 at 09:25
  • 1
    @Hans your error message must point to a line number which is not inside your new `foo/1`. Something else you're doing outside of `foo/1` is causing the error. I believe I answered your original question properly as stated, and now you are introducing new questions. You should mark this one answered and create e new question. – lurker Feb 19 '15 at 10:49
2

This might also be what you are looking for. No sorting, just use of maximum and minimum:

:- use_module(library(clpfd)).

listl( LSize, List ) :-
  length( List, LSize ),
  domain(List, 1, 9),

  maximum( MaxL, List ),
  minimum( MinL, List ),

  all_different(List),
  LSize #= MaxL - MinL + 1,

  labeling( [], List ).

With a small test:

| ?- listl( 4, L ).
L = [1,2,3,4] ? ;
L = [1,2,4,3] ? ;
L = [1,3,2,4] ? ;
L = [1,3,4,2] ? 
yes
| ?- 

Disclaimer: The question was hard to understand.

MortenM
  • 562
  • 2
  • 12