So, the basic idea is to construct a matrix like this:
         spot1  spot2  spot3
team1      5      0      -1
team2      4      1      -1 
...

With the 'spots' the spaces to fill in for each team. There are max 3 
spots/team. If a spot is not used, -1 should be put. If it is used, I put 
the number of the player (index in the defined vector). For example, with a 
very small player vector:
(def players [{:level 3} {:level 4} {:level 7} {:level 1}])


The problems I'm facing so far:

1/ using $distinct to make sure each player is only assigned one spot on 
one team.
The value of -1 can be used more than once, because it's used as filler 
where no player is assigned.

(defn base-model [players]
  (concat (for [team (range (quot (count players) 2)), spot (range 3)] 
    ($in [:p team spot] (range -1 (count players)) ))))
 
(def all (for [team (range (quot (count players) 2)), spot (range 3)] 
  [:p team spot]))

(solutions (conj (base-model ps) ($distinct all) ))


doesn't give any solutions, obviously: there are always more possible spots 
to fill than there are players. A work-around would be to add more negative 
numbers as 'fillers', and adding some other constraints so that at least 
two of the three spots per team are positive. I'll make sure the vector is 
sorted anyway, on level first and experience second (with the player having 
the highest number in the front of each team, as captain), so that might be 
rather easy to do. 
But it feels rather hacky.

2/ getting player data with $nth, so constraints based on player 
characteristics can be added. 
For example, if I want player of team 1 on slot 1 having a level of more 
than 2, I'd expect something like this to work:
(solutions (conj (base-model ps) ($> (:level ($nth players [:p 0 0])) 2)  ))
which translates to me: take player on index given by [:p 0 0] from 
'players', get the level from that player and check if it's higher than 2. 
This, however, does not work:
IllegalArgumentException No method in multimethod '->choco*' for dispatch 
value: null  clojure.lang.MultiFn.getFn (MultiFn.java:156)
I clearly misunderstand how $nth (or how loco in general) works. How I can 
use my player characteristics (the vector of player data maps) for adding 
constraints?

Thx, qsys




Op dinsdag 6 oktober 2015 12:10:23 UTC+2 schreef Kurt Sys:
>
> Reading the thread: generate al possible teams 
> <https://groups.google.com/forum/#!searchin/clojure/generate$20all$20possible$20teams/clojure/DeCBCD_dwRo/OyjJPgHXCAAJ>,
>  
> I realized I was facing a slightly similar problem. Although many valuable 
> suggestions were made, I'm very interested in one made 
> <https://groups.google.com/d/msg/clojure/DeCBCD_dwRo/nw4aW4zwCAAJ> by 
> puzzler, 
> i.e. using loco (unless another method/library is more useful, suggestions 
> are welcome).
>
> Now, the problem description: 
> 1/ I have a set of players which must be divided in teams of two. If only 
> teams of two is not possible, teams of three are allowed as well.
> 2/ Every player has a set of characteristics. Based on these 
> characteristics, some teams are not allowed, some are, and some are 
> prefered.
>
> There are quite a few characteristics, so I'll build up the first few:
> 1/ The main characteristic is 'level', ranging from 0-7. Only teams of two 
> with total level of 5 or more are allowed. 
> For teams of three, there are separate rules: there must be at least one 
> level 3. If the highest level is 3, than no two levels 1 or less are 
> allowed. 
>
> 2/ There is a characteristic 'experience' as well. Taking into account the 
> exprience, there are more exceptions:
> A level 3 and a level 1 is allowed (in contrast to rule 1: total should be 
> at least 5), if the experience of level 1 is high enough
> A level 4 and a level 1 are not allowed together, if the experience of 
> level 1 is not high enough
> Two levels 2 are allowed, if both are experienced enough
>
> So far, it's still pretty easy to find a solution: rank according to level 
> and experience, and take each time the top and bottom from the list. That 
> should be pretty close to the most optimal solution. But there are more 
> characteristics for each player:
>
> 3/ There are preferences to put some players together, scored from 1 
> (avoid teaming them) to 7 (high preference to team them). Based on these 
> preferences, 'team preferences' might be calculated. If no 'preference' is 
> given, a value of 4 is assumed. In this example, I scored them per player, 
> but it might be done per team as well.
>
> 4/ Some players might have a 'handicap', so they need another levels to 
> team with. If possible, the handicaps should be used, but they may be 
> omitted if there is no other solution. In an extended version, a preference 
> level for a handicap for a certain player may be set as well.
>
> There are quite a few of handicaps (like 4) and rules (like 1 and 2, which 
> are just a small subset of all handicaps and rules.
>
> The number of players will not be very high, up to max 100, so max 50 
> teams, which might be important, since I don't think heuristics will have a 
> high benefit in this case (but I might be wrong).
>
> An example: 
>
> The players:
> P1 {:level 0 :experience 0}
> P2 {:level 2 :experience 17}
> P3 {:level 3 :experience 23 :handicap :cl }
> P4 {:level 3 :experience 27 :preference {P2 2, P3 6}}
> P5 {:level 6 :experience 50}
> P6 {:level 5 :experience 55 :preference {P2 1}}
>
> The handicap description: {:cl :needs-level 5}
>
> The solution?
> (solve [P1 P2 P3 P4 P5 P6])
> results in a set with possible solutions (possibly with some timeout or 
> after the first x solutions are found):
> #{ 
>   { [ [P6 P1] [P5 P2] [P4 P3] ]
>     :unmatched-handicaps 1
>     :team-preferences [4 4] [4 4] [4 6] }
>   { [ [P5 P1] [P6 P2] [P4 P3] ]
>     :unmatched-handicaps 1
>     :team-preferences [4 4] [1 4] [4 6] }
>   { [ [P5 P3] [P6 P1] [P4 P2] ]
>     :unmatched-handicaps 0
>     :team-preferences [4 4] [4 4] [2 4] }
>   ... }
>
> Since puzzler said 'I can provide an example of that if you are 
> interested' (for generating 'balanced teams' with restrictions with 
> loco)... I'm interested :).
>
> Thanks.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to