Generate all partitions of integer array [duplicate] - c++

I have a set of distinct values. I am looking for a way to generate all partitions of this set, i.e. all possible ways of dividing the set into subsets.
For instance, the set {1, 2, 3} has the following partitions:
{ {1}, {2}, {3} },
{ {1, 2}, {3} },
{ {1, 3}, {2} },
{ {1}, {2, 3} },
{ {1, 2, 3} }.
As these are sets in the mathematical sense, order is irrelevant. For instance, {1, 2}, {3} is the same as {3}, {2, 1} and should not be a separate result.
A thorough definition of set partitions can be found on Wikipedia.

I've found a straightforward recursive solution.
First, let's solve a simpler problem: how to find all partitions consisting of exactly two parts. For an n-element set, we can count an int from 0 to (2^n)-1. This creates every n-bit pattern, with each bit corresponding to one input element. If the bit is 0, we place the element in the first part; if it is 1, the element is placed in the second part. This leaves one problem: For each partition, we'll get a duplicate result where the two parts are swapped. To remedy this, we'll always place the first element into the first part. We then only distribute the remaining n-1 elements by counting from 0 to (2^(n-1))-1.
Now that we can partition a set into two parts, we can write a recursive function that solves the rest of the problem. The function starts off with the original set and finds all two-part-partitions. For each of these partitions, it recursively finds all ways to partition the second part into two parts, yielding all three-part partitions. It then divides the last part of each of these partitions to generate all four-part partitions, and so on.
The following is an implementation in C#. Calling
Partitioning.GetAllPartitions(new[] { 1, 2, 3, 4 })
yields
{ {1, 2, 3, 4} },
{ {1, 3, 4}, {2} },
{ {1, 2, 4}, {3} },
{ {1, 4}, {2, 3} },
{ {1, 4}, {2}, {3} },
{ {1, 2, 3}, {4} },
{ {1, 3}, {2, 4} },
{ {1, 3}, {2}, {4} },
{ {1, 2}, {3, 4} },
{ {1, 2}, {3}, {4} },
{ {1}, {2, 3, 4} },
{ {1}, {2, 4}, {3} },
{ {1}, {2, 3}, {4} },
{ {1}, {2}, {3, 4} },
{ {1}, {2}, {3}, {4} }.
using System;
using System.Collections.Generic;
using System.Linq;
namespace PartitionTest {
public static class Partitioning {
public static IEnumerable<T[][]> GetAllPartitions<T>(T[] elements) {
return GetAllPartitions(new T[][]{}, elements);
}
private static IEnumerable<T[][]> GetAllPartitions<T>(
T[][] fixedParts, T[] suffixElements)
{
// A trivial partition consists of the fixed parts
// followed by all suffix elements as one block
yield return fixedParts.Concat(new[] { suffixElements }).ToArray();
// Get all two-group-partitions of the suffix elements
// and sub-divide them recursively
var suffixPartitions = GetTuplePartitions(suffixElements);
foreach (Tuple<T[], T[]> suffixPartition in suffixPartitions) {
var subPartitions = GetAllPartitions(
fixedParts.Concat(new[] { suffixPartition.Item1 }).ToArray(),
suffixPartition.Item2);
foreach (var subPartition in subPartitions) {
yield return subPartition;
}
}
}
private static IEnumerable<Tuple<T[], T[]>> GetTuplePartitions<T>(
T[] elements)
{
// No result if less than 2 elements
if (elements.Length < 2) yield break;
// Generate all 2-part partitions
for (int pattern = 1; pattern < 1 << (elements.Length - 1); pattern++) {
// Create the two result sets and
// assign the first element to the first set
List<T>[] resultSets = {
new List<T> { elements[0] }, new List<T>() };
// Distribute the remaining elements
for (int index = 1; index < elements.Length; index++) {
resultSets[(pattern >> (index - 1)) & 1].Add(elements[index]);
}
yield return Tuple.Create(
resultSets[0].ToArray(), resultSets[1].ToArray());
}
}
}
}

Please refer to the Bell number, here is a brief thought to this problem:
consider f(n,m) as partition a set of n element into m non-empty sets.
For example, the partition of a set of 3 elements can be:
1) set size 1: {{1,2,3}, } <-- f(3,1)
2) set size 2: {{1,2},{3}}, {{1,3},{2}}, {{2,3},{1}} <-- f(3,2)
3) set size 3: {{1}, {2}, {3}} <-- f(3,3)
Now let's calculate f(4,2):
there are two ways to make f(4,2):
A. add a set to f(3,1), which will convert from {{1,2,3}, } to {{1,2,3}, {4}}
B. add 4 to any of set of f(3,2), which will convert from
{{1,2},{3}}, {{1,3},{2}}, {{2,3},{1}}
to
{{1,2,4},{3}}, {{1,2},{3,4}}
{{1,3,4},{2}}, {{1,3},{2,4}}
{{2,3,4},{1}}, {{2,3},{1,4}}
So f(4,2) = f(3,1) + f(3,2)*2
which result in f(n,m) = f(n-1,m-1) + f(n-1,m)*m
Here is Java code for get all partitions of set:
import java.util.ArrayList;
import java.util.List;
public class SetPartition {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for(int i=1; i<=3; i++) {
list.add(i);
}
int cnt = 0;
for(int i=1; i<=list.size(); i++) {
List<List<List<Integer>>> ret = helper(list, i);
cnt += ret.size();
System.out.println(ret);
}
System.out.println("Number of partitions: " + cnt);
}
// partition f(n, m)
private static List<List<List<Integer>>> helper(List<Integer> ori, int m) {
List<List<List<Integer>>> ret = new ArrayList<>();
if(ori.size() < m || m < 1) return ret;
if(m == 1) {
List<List<Integer>> partition = new ArrayList<>();
partition.add(new ArrayList<>(ori));
ret.add(partition);
return ret;
}
// f(n-1, m)
List<List<List<Integer>>> prev1 = helper(ori.subList(0, ori.size() - 1), m);
for(int i=0; i<prev1.size(); i++) {
for(int j=0; j<prev1.get(i).size(); j++) {
// Deep copy from prev1.get(i) to l
List<List<Integer>> l = new ArrayList<>();
for(List<Integer> inner : prev1.get(i)) {
l.add(new ArrayList<>(inner));
}
l.get(j).add(ori.get(ori.size()-1));
ret.add(l);
}
}
List<Integer> set = new ArrayList<>();
set.add(ori.get(ori.size() - 1));
// f(n-1, m-1)
List<List<List<Integer>>> prev2 = helper(ori.subList(0, ori.size() - 1), m - 1);
for(int i=0; i<prev2.size(); i++) {
List<List<Integer>> l = new ArrayList<>(prev2.get(i));
l.add(set);
ret.add(l);
}
return ret;
}
}
And result is:
[[[1, 2, 3]]]
[[[1, 3], [2]], [[1], [2, 3]], [[1, 2], [3]]]
[[[1], [2], [3]]]
Number of partitions: 5

Just for fun, here's a shorter purely iterative version:
public static IEnumerable<List<List<T>>> GetAllPartitions<T>(T[] elements) {
var lists = new List<List<T>>();
var indexes = new int[elements.Length];
lists.Add(new List<T>());
lists[0].AddRange(elements);
for (;;) {
yield return lists;
int i,index;
for (i=indexes.Length-1;; --i) {
if (i<=0)
yield break;
index = indexes[i];
lists[index].RemoveAt(lists[index].Count-1);
if (lists[index].Count>0)
break;
lists.RemoveAt(index);
}
++index;
if (index >= lists.Count)
lists.Add(new List<T>());
for (;i<indexes.Length;++i) {
indexes[i]=index;
lists[index].Add(elements[i]);
index=0;
}
}
Test here:https://ideone.com/EccB5n
And a simpler recursive version:
public static IEnumerable<List<List<T>>> GetAllPartitions<T>(T[] elements, int maxlen) {
if (maxlen<=0) {
yield return new List<List<T>>();
}
else {
T elem = elements[maxlen-1];
var shorter=GetAllPartitions(elements,maxlen-1);
foreach (var part in shorter) {
foreach (var list in part.ToArray()) {
list.Add(elem);
yield return part;
list.RemoveAt(list.Count-1);
}
var newlist=new List<T>();
newlist.Add(elem);
part.Add(newlist);
yield return part;
part.RemoveAt(part.Count-1);
}
}
https://ideone.com/Kdir4e

Here is a non-recursive solution
class Program
{
static void Main(string[] args)
{
var items = new List<Char>() { 'A', 'B', 'C', 'D', 'E' };
int i = 0;
foreach (var partition in items.Partitions())
{
Console.WriteLine(++i);
foreach (var group in partition)
{
Console.WriteLine(string.Join(",", group));
}
Console.WriteLine();
}
Console.ReadLine();
}
}
public static class Partition
{
public static IEnumerable<IList<IList<T>>> Partitions<T>(this IList<T> items)
{
if (items.Count() == 0)
yield break;
var currentPartition = new int[items.Count()];
do
{
var groups = new List<T>[currentPartition.Max() + 1];
for (int i = 0; i < currentPartition.Length; ++i)
{
int groupIndex = currentPartition[i];
if (groups[groupIndex] == null)
groups[groupIndex] = new List<T>();
groups[groupIndex].Add(items[i]);
}
yield return groups;
} while (NextPartition(currentPartition));
}
private static bool NextPartition(int[] currentPartition)
{
int index = currentPartition.Length - 1;
while (index >= 0)
{
++currentPartition[index];
if (Valid(currentPartition))
return true;
currentPartition[index--] = 0;
}
return false;
}
private static bool Valid(int[] currentPartition)
{
var uniqueSymbolsSeen = new HashSet<int>();
foreach (var item in currentPartition)
{
uniqueSymbolsSeen.Add(item);
if (uniqueSymbolsSeen.Count <= item)
return false;
}
return true;
}
}

Here is a solution in Ruby that's about 20 lines long:
def copy_2d_array(array)
array.inject([]) {|array_copy, item| array_copy.push(item)}
end
#
# each_partition(n) { |partition| block}
#
# Call the given block for each partition of {1 ... n}
# Each partition is represented as an array of arrays.
# partition[i] is an array indicating the membership of that partition.
#
def each_partition(n)
if n == 1
# base case: There is only one partition of {1}
yield [[1]]
else
# recursively generate the partitions of {1 ... n-1}.
each_partition(n-1) do |partition|
# adding {n} to a subset of partition generates
# a new partition of {1 ... n}
partition.each_index do |i|
partition_copy = copy_2d_array(partition)
partition_copy[i].push(n)
yield (partition_copy)
end # each_index
# Also adding the set {n} to a partition of {1 ... n}
# generates a new partition of {1 ... n}
partition_copy = copy_2d_array(partition)
partition_copy.push [n]
yield(partition_copy)
end # block for recursive call to each_partition
end # else
end # each_partition
(I'm not trying to shill for Ruby, I just figured that this solution may easier for some readers to understand.)

A trick I used for a set of N members.
1. Calculate 2^N
2. Write each number between 1 and N in binary.
3. You will get 2^N binary numbers each of length N and each number tells you how to split the set into subset A and B. If the k'th digit is 0 then put the k'th element in set A otherwise put it in set B.

I have implemented Donald Knuth's very nice Algorith H that lists all partitions in Matlab
https://uk.mathworks.com/matlabcentral/fileexchange/62775-allpartitions--s--
http://www-cs-faculty.stanford.edu/~knuth/fasc3b.ps.gz
function [ PI, RGS ] = AllPartitions( S )
%% check that we have at least two elements
n = numel(S);
if n < 2
error('Set must have two or more elements');
end
%% Donald Knuth's Algorith H
% restricted growth strings
RGS = [];
% H1
a = zeros(1,n);
b = ones(1,n-1);
m = 1;
while true
% H2
RGS(end+1,:) = a;
while a(n) ~= m
% H3
a(n) = a(n) + 1;
RGS(end+1,:) = a;
end
% H4
j = n - 1;
while a(j) == b(j)
j = j - 1;
end
% H5
if j == 1
break;
else
a(j) = a(j) + 1;
end
% H6
m = b(j) + (a(j) == b (j));
j = j + 1;
while j < n
a(j) = 0;
b(j) = m;
j = j + 1;
end
a(n) = 0;
elementsd
%% get partitions from the restricted growth stirngs
PI = PartitionsFromRGS(S, RGS);
end

def allPossiblePartitions(l): # l is the list whose possible partitions have to be found
# to get all possible partitions, we consider the binary values from 0 to 2**len(l))//2-1
"""
{123} --> 000 (0)
{12} {3} --> 001 (1)
{1} {2} {3} --> 010 (2)
{1} {23} --> 011 (3) --> (0 to (2**3//2)-1)
iterate over each possible partitions,
if there are partitions>=days and
if that particular partition contains
more than one element then take max of all elements under that partition
ex: if the partition is {1} {23} then we take 1+3
"""
for i in range(0,(2**len(l))//2):
s = bin(i).replace('0b',"")
s = '0'*(len(l)-len(s)) + s
sublist = []
prev = s[0]
partitions = []
k = 0
for i in s:
if (i == prev):
partitions.append(l[k])
k+=1
else:
sublist.append(partitions)
partitions = [l[k]]
k+=1
prev = i
sublist.append(partitions)
print(sublist)

Related

Unable to understand lists in dart consider the example provided

I am developing an app in flutter. For which I am using lists of map but there something that I am unable to undertand. Consider the following cases:
SCENARIO 1
void main() {
List<Map<String,String>> _reminders = [];
Map<String , String> _tempMap = {};
for (int i = 0; i < 5; i++) {
_tempMap.clear();
_tempMap.putIfAbsent('M' , () => 'm ' + i.toString());
_tempMap.putIfAbsent('D' , () => 'd : ' + i.toString());
_reminders.add(_tempMap);
// or _reminders.insert(i, _tempMap);
}
print(_reminders.toString());
return;
}
to which the result is as follows
[{M: m 4, D: d : 4}, {M: m 4, D: d : 4}, {M: m 4, D: d : 4}, {M: m 4, D: d : 4}, {M: m 4, D: d : 4}]
SCENARIO 2
void main() {
List<Map<String,String>> _reminders = [];
for (int i = 0; i < 5; i++) {
Map<String , String> _tempMap = {};
_tempMap.putIfAbsent('M' , () => 'm ' + i.toString());
_tempMap.putIfAbsent('D' , () => 'd : ' + i.toString());
_reminders.add(_tempMap);;
}
print(_reminders.toString());
return;
}
to which the result is as follows
[{M: m 0, D: d : 0}, {M: m 1, D: d : 1}, {M: m 2, D: d : 2}, {M: m 3, D: d : 3}, {M: m 4, D: d : 4}]
As far as I understand, these scenarios should give similar results. Also in my use case scenario 2 is the correct way as it gives me the result that I want. Please note the above examples have been changed to similify the question. The usage in my original code is much more complex.
Dart, like many other programming languages including java, stores objects as reference, and not contiguous memory blocks. In the first case, in all the iterations of the loop, you have added the same Map using the _reminders.add(_tempMap). Your intuition that "Everytime I add the Map, a copy is created of the current state of Map and that copy is appended to the list" is incorrect.
From my understanding, both are different
The problem is with _tempMap.clear(); in the SCENARIO 1. You have used the global variable for map object and when you apply clear inside the for loop all the previously added entries will be cleared and map becomes empty.
when i = 0 => {} => clear() => all entries will be cleared => New item inserted.
when i = 1 => {"Item inserted in 0th iteration"} => clear() => all entries will be cleared => New item inserted.
So for every iteration map is cleared and holds only last iterated value. After for loop is completed it contains only the last iterated value(i=4) since we are clearing the global map variable every time when a new iteration starts.
EDIT :
You can print the map values inside the for loop and can check yourself.
for (int i = 0; i < 5; i++) {
print('\n $i => ${_tempMap} \n');

how an unordered_map is initialized with the values of array

I have come across a code where i get confused , An unordered_map is initialised like below
std::unordered_map<std::string, int> wordMap;
// Inserting elements through an initializer_list
wordMap.insert({ {"First", 1}, {"Second", 2}, {"Third", 3} } );
But what surprise me is the below code
int arr[] = { 1, 5, 2, 1, 3, 2, 1 };
unordered_map<int, int> hash;
for (int i = 0; i < n; i++)
hash[arr[i]]++;
Here i am not getting how key and value is inserted in the map
Here, In unordered_map, hash[arr[i]]++; works in this way:
It searches for a key (arr[i]). If it is found, the corresponding value is incremented by 1.
If it is not found, a new element will be created with key arr[i] and because value is of type int, default value of 0 is stored for it. Because of ++ operator, it will be incremented by one. So, at the end of the operation, the value will be 1.
To be very explicit for your example, it works like this:
i = 0 => arr[i] = 1 => Not present in map => New pair added => hash: [{1, 1}]
i = 1 => arr[i] = 5 => Not present in map => New pair added => hash: [{1, 1}, {5, 1}]
i = 2 => arr[i] = 2 => Not present in map => New pair added => hash: [{1, 1}, {5, 1}, {2, 1}]
i = 3 => arr[i] = 1 => Present in map => Existing pair updated => hash: [{1, 2}, {5, 1}, {2, 1}]
i = 4 => arr[i] = 3 => Not present in map => New pair added => hash: [{1, 2}, {5, 1}, {2, 1}, {3, 1}]
i = 5 => arr[i] = 2 => Present in map => Existing pair updated => hash: [{1, 2}, {5, 1}, {2, 2}, {3, 1}]
i = 6 => arr[i] = 1 => Present in map => Existing pair updated => hash: [{1, 3}, {5, 1}, {2, 2}, {3, 1}]
The order mentioned here might be different from actual one. The above explanation is just to explain things.
The key of the unordered map must be unique so all 1:s will be combined. But when they do combine the loop will add 1 to the value side:
hash[arr[i]]++ will be equal to this example: hash[1] += 1;
Since there are three 1 values, hash[1] will end up with a value of 3. You will find two records of the value 2 and this will make hash[2] = 2.
#include <iostream>
#include <unordered_map>
int main()
{
int arr[] = { 1, 5, 2, 1, 3, 2, 1 };
std::unordered_map<int, int> hash;
for (int i = 0; i < 7; i++) {
hash[arr[i]] += 1;
}
for (auto i : hash) {
printf("%i:%i\n", i.first, i.second);
}
}
# Output:
# 3:1
# 2:2
# 5:1
# 1:3
operator[] checks if the element exists. If it doesn't then it creates one using default constructor and returns a reference (or const reference to it). ie :
hash[arr[0]]++
it creates hash[1]first
which is
hash[1]++ => hash[1]=hash[1]+1 which is 0+1 ( since hash[1] at the begining was 0 by default.. )
when it get to the second 1 it become hash[1]=hash[1]+1 = 2 ...
..ect same for other values
basically it s creating & counting the number of the duplicates in the array
at the end it gives you
hash[1]=3
hash[2]=2
hash[3]=1
hash[5]=1

Making groups (combinations) of objects using their min/max values

First of all, this is my first question, you can tell me how to improve it and what tags to use.
What I am trying to do is I have a bunch of objects that have minimal and maximal values by those values you can deduce if two objects have some sort of overlapping value and thus they can be put together in a group
This question might need dynamic programming to solve.
example objects:
1 ( min: 0, max: 2 )
2 ( min: 1, max: 3 )
3 ( min: 2, max: 4 )
4 ( min: 3, max: 5 )
object 1 can be grouped with objects 2, 3
object 2 can be grouped with objects 1, 3, 4
object 3 can be grouped with objects 1, 2, 4
object 4 can be grouped with objects 2, 3
as you can see there are multiple ways to group those elements
[1, 2]
[3, 4]
[1]
[2, 3]
[4]
[1]
[2, 3, 4]
[1, 2, 3]
[4]
now there should be some sort of rule to deduce which of the solutions is the best solution
for example least amount of groups
[1, 2]
[3, 4]
or
[1]
[2, 3, 4]
or
[1, 2, 3]
[4]
or most objects in one group
[1]
[2, 3, 4]
or
[1, 2, 3]
[4]
or any other rule that uses another attribute of said objects to compare the solutions
what I have now:
$objects = [...objects...];
$numberOfObjects = count($objects);
$groups = [];
for ($i = 0; $i < $numberOfObjects; $i++) {
$MinA = $objects[$i]['min'];
$MaxA = $objects[$i]['max'];
$groups[$i] = [$i];
for ($j = $i + 1; $j < $numberOfObjects; $j++) {
$MinB = $objects[$j]['min'];
$MaxB = $objects[$j]['max'];
if (($MinA >= $MinB && $MinA <= $MaxB) || ($MaxA >= $MinB && $MaxA <= $MaxB) || ($MinB >= $MinA && $MinB <= $MaxA)) {
array_push($groups[$i], $j);
}
}
}
this basically creates an array with indexes of objects that can be grouped together
from this point, I don't know how to proceed, how to generate all the solution and then check each of them how good it is, and the pick the best one
or maybe there is even better solution that doesn't use any of this?
PHP solutions are preferred, although this problem is not PHP-specific
When I was first looking at your algorithm, I was impressed by how efficient it is :)
Here it is rewritten in javascript, because I moved away from perl a good while ago:
function setsOf(objects){
numberOfObjects = objects.length
groups = []
let i
for (i = 0; i < numberOfObjects; i++) {
MinA = objects[i]['min']
MaxA = objects[i]['max']
groups[i] = [i]
for (j = i + 1; j < numberOfObjects; j++) {
MinB = objects[j]['min']
MaxB = objects[j]['max']
if ((MinA >= MinB && MinA <= MaxB) || (MaxA >= MinB && MaxA <= MaxB) ||
(MinB >= MinA && MinB <= MaxA)) {
groups[i].push(j)
}
}
}
return groups
}
if you happen to also think well in javascript, you might find this form more direct (it is identical, however):
function setsOf(objects){
let groups = []
objects.forEach((left,i) => {
groups[i]=[i]
Array.from(objects).splice(i+1).forEach((right, j) => {
if ((left.min >= right.min && left.min <= right.max) ||
(left.max >=right.max && left.max <= right.max) ||
(right.min >= left.min && right.min <= left.max))
groups[i].push(j+i+1)
})
})
return groups
}
so if we run it, we get:
a = setsOf([{min:0, max:2}, {min:1, max:3}, {min:2, max:4}, {min:3, max: 5}])
[Array(3), Array(3), Array(2), Array(1)]0: Array(3)1: Array(3)2: Array(2)3: Array(1)length: 4__proto__: Array(0)
JSON.stringify(a)
"[[0,1,2],[1,2,3],[2,3],[3]]"
and it does impressively catch the compound groups :) a weakness is that it is capturing groups containing more objects than necessary, without capturing all available objects. You seem to have a very custom selection criteria. To me, it seems like the groups should either be every last intersecting subset, or only subsets where each element in the group provides unique coverage: [0,1], [0,2], [1,2], [1,3], [2,3], [0,1,3]
the algorithm for that is perhaps more involved. this was my approach, and it is nowhere near as terse and elegant as yours, but it works:
function intersectingGroups (mmvs) {
const min = []
const max = []
const muxo = [...mmvs]
mmvs.forEach(byMin => {
mmvs.forEach(byMax => {
if (byMin.min === byMax.min && byMin.max === byMax.max) {
console.log('rejecting identity', byMin, byMax)
return // identity
}
if (byMax.min > byMin.max) {
console.log('rejecting non-overlapping objects', byMin, byMax)
return // non-overlapping objects
}
if ((byMax.max <= byMin.max) || (byMin.min >= byMax.min)) {
console.log('rejecting non-expansive coverage or inversed order',
byMin, byMax)
return // non-expansive coverage or inversed order
}
const entity = {min: byMin.min, max: byMax.max,
compositeOf: [byMin, byMax]}
if(muxo.some(mv => mv.min === entity.min && mv.max === entity.max))
return // enforcing Set
muxo.push(entity)
console.log('adding', byMin, byMax, muxo)
})
})
if(muxo.length === mmvs.length) {
return muxo.filter(m => 'compositeOf' in m)
// solution
} else {
return intersectingGroups(muxo)
}
}
now there should be some sort of rule to deduce which of the solutions is the best solution
Yeah, so, usually for puzzles or for a specification you are fulfilling, that would be given as part of the problem. As it is, you want a general method that is adaptable. It's probably best to make an object that can be configured with the results and accepts rules, then load the rules you are interested in, and the results from the search, and see what rules match where. For example, using your algorithm and sample criteria:
least amount of groups
start with code like:
let reviewerFactory = {
getReviewer (specification) { // generate a reviewer
return {
matches: [], // place to load sets to
criteria: specification,
review (objects) { // review the sets already loaded
let group
let results = {}
this.matches.forEach(mset => {
group = [] // gather each object from the initial set for each match in the result set
mset.forEach(m => {
group.push(objects[m])
})
results[mset] = this.criteria.scoring(group) // score the match relative to the specification
})
return this.criteria.evaluation(results) // pick the best score
}
}
},
specifications: {}
}
now you can add specifications like this one for least amount of groups:
reviewerFactory.specifications['LEAST GROUPS'] = {
scoring: function (set) { return set.length },
evaluation: function (res) { return Object.keys(res).sort((a,b) => res[a] - res[b])[0] }
}
then you can use that in the evaluation of a set:
mySet = [{min:0, max:2}, {min:1, max:3}, {min:2, max:4}, {min:3, max: 5}]
rf = reviewerFactory.getReviewer(reviewerFactory.specifications['LEAST GROUPS'])
Object {matches: Array(0), criteria: Object, review: function}
rf.matches = setsOf(mySet)
[Array(3), Array(3), Array(2), Array(1)]
rf.review(mySet)
"3"
or, most objects:
reviewerFactory.specifications['MOST GROUPS'] = {
scoring: function (set) { return set.length },
evaluation: function (res) { return Object.keys(res).sort((a,b) => res[a] - res[b]).reverse()[0] }
}
mySet = [{min:0, max:2}, {min:1, max:3}, {min:2, max:4}, {min:3, max: 5}]
reviewer = reviewerFactory.getReviewer(reviewerFactory.specifications['MOST GROUPS'])
reviewer.matches = setsOf(mySet)
reviewer.review(mySet)
"1,2,3"
Of course this is arbitrary, but so are the criteria, by definition in the OP. Likewise, you would have to change the algorithms here to work with my intersectingGroups function because it doesn't return indices. But this is what you are looking for I believe.

Scala accessing list objects and evaluating number of cycles

Scala accessing list objects and evaluating number of cycles
I have list of objects
case class ItemDesc(a: Int, b: Int, c: Int, d: Int,e: Int, f: Int, g: Int desc: String)
val example = List(ItemDesc(6164,6165,6166,-6195,-6175,-6186,-6195, The values are correct), ItemDesc(14879,-14879,14879,-14894, 14879,14879,14894, The values are ok), ItemDesc(19682,-19690,-19682,19694,19690,19682,19694,The values are good),ItemDesc(5164,-5165,-5166,-6195,5165,5166,6195,The values are correct),ItemDesc(5879,5879,5879,5894,5879,5879,5879,The values are ok))
From the 'example' List, I want to access object 'ItemDesc'. And get the count of cycles. how many times it turns from negative to positive and stays positive for >= 2 seconds.
If >= 2 seconds it is a cycle.
Example 1: (6164,6165,6166,-6195,-6175,-6186,-6195, good)
No. of cycles is 2.
Reason: As we move from 1st element of list to 3rd element, we had 2 intervals which means 2 seconds. Interval is >= 2. So it is one cycle. As we move to 3rd element of list to 4th element, it is a negative value. So we start counting from 4th element and move to 7th element and all elements have same negative sign. we had 3 intervals which means 3 seconds. Interval is >= 2. So it is one cycle. We start counting intervals fresh from zero as one number changes from positive to negative and vice-versa.
Example 2: (14879,-14879,14879,-14894, 14879,14879,14894,better)
No. of cycles is 1.
Reason: As we move from 1st element of list to 2nd element, the sign changes to negative. So we start counting the interval from zero. From element 2 to 3, the sign changes to negative. so interval counter is zero. From element 3 to 4, the sign changes to negative. interval counter is zero. From 5th to 7th all values have same sign, we had 2 intervals which means 2 seconds. Interval is >= 2. So it is one cycle.
Example 3: (5164,-5165,-5166,-6195,5165,5166,6195,good)
No. of cycles is 2
The below code which I wrote is not giving me the no. of cycles which I am looking for. Appreciate help in fixing it.
object findCycles {
def main(args: Array[String]) {
var numberOfPositiveCycles = 0
var numberOfNegativeCycles = 0
var numberOfCycles = 0
case class itemDesc(a: Int, b: Int, c: Int, d: Int, reason: String)
val example = List(ItemDesc(6164,6165,6166,-6195,-6175,-6186,-6195, The values are correct), ItemDesc(14879,-14879,14879,-14894, 14879,14879,14894, The values are ok), ItemDesc(19682,-19690,-19682,19694,19690,19682,19694,The values are good),ItemDesc(5164,-5165,-5166,-6195,5165,5166,6195,The values are correct),ItemDesc(5879,5879,5879,5894,5879,5879,5879,The values are ok))
val data2 = example.map(x => getInteger(x)).filter(_ != "unknown").map(_.toString.toInt)
//println(data2)
var nCycle = findNCycle(data2)
println(nCycle)
}
def getInteger(obj: Any) = obj match {
case n: Int => obj
case _ => "unknown"
}
def findNCycle(obj: List[Int]) : Int = {
def NegativeCycles(fit: itemDesc): Int = {
if (fit.a < 0 && fit.b < 0 && fit.c < 0) || if( fit.b < 0 && fit.c < 0 && fit.d < 0)
{
numberOfNegativeCycles += 1
}
}
//println("negative cycle="+cycles)
def PositiveCycles(fit: itemDesc): Int = {
if (fit.a > 0 && fit.b > 0 && fit.c > 0) || if( fit.b > 0 && fit.c > 0 && fit.d > 0)
{
numberOfPositiveCycles += 1
}
}
//println("positive cycle="+cycles)
numberOfCycles = numberOfPositiveCycles + numberOfNegativeCycles
return numberOfCycles
}
}
For reference on the logic you can refer to- Number of Cycles from list of values, which are mix of positives and negatives in Spark and Scala
Ok this is rough but I think it does what you want. I'm sure there is a more elegant way to do the split method.
I haven't used your ItemDesc as its simpler to demonstrate the problem given the examples you gave.
object CountCycles extends App {
// No. of cycles is 1.
val example1 = List(1, 2, 3, 4, 5, 6, -15, -66)
// No. of cycles is 3.
val example2 = List(11, 22, 33, -25, -36, -43, 20, 25, 28)
// No. of cycles is 8
val example3 = List(1, 4, 82, 5, 6, -2, -12, -22, -32, 100, 102, 100, 102, 0, 0, -2, -12, -22, -32, 4, 82, 5, 6, -6, 8, -6, -6, 8, 8, -5, -6, -7, 9, 8, 6, -5, -6, -7)
def differentSign(x: Int, y: Int): Boolean =
(x < 0) != ( y < 0)
// return a list of sections
def split(l: List[Int]): List[List[Int]] =
l match {
case Nil ⇒ Nil
case h :: _ ⇒
val transition: Int = l.indexWhere(differentSign(h, _))
if (transition < 0) List(l)
else {
val (head, tail) = l.splitAt(transition)
head :: split(tail)
}
}
def count(l: List[Int]): Int = {
val pos: List[List[Int]] = split(l)
// count is the number of sections of length > 2
pos.count(_.length > 2)
}
println(count(example1)) // 1
println(count(example2)) // 3
println(count(example3)) // 8
}
This should be a working solution for the case where you have 7 items in the sample as shown in the description. If your case class changes and instead has a list of values then the implicit helper can be replaced with a simple call to the accessor
import scala.annotation.tailrec
import scala.language.implicitConversions
object CyclesCounter extends App {
val examples = List(
ItemDesc(6164,6165,6166,-6195,-6175,-6186,-6195, "The values are correct"),
ItemDesc(14879,-14879,14879,-14894, 14879,14879,14894, "The values are ok"),
ItemDesc(19682,-19690,-19682,19694,19690,19682,19694,"The values are good"),
ItemDesc(5164,-5165,-5166,-6195,5165,5166,6195,"The values are correct"),
ItemDesc(5879,5879,5879,5894,5879,5879,5879,"The values are ok"))
val counter = new CycleCounter
// Add the index for more readable output
examples.zipWithIndex.foreach{ case (item, index) => println(s"Item at index $index has ${counter.cycleCount(item)} cycles")}
}
class CycleCounter {
def cycleCount(item: ItemDesc): Int = {
#tailrec
def countCycles(remainingValues: List[Int], cycles: Int): Int = {
if (remainingValues.isEmpty) cycles
else {
val headItems = {
if (remainingValues.head < 0) remainingValues.takeWhile(_ < 0)
else remainingValues.takeWhile(_ >= 0)
}
val rest = remainingValues.drop(headItems.length)
if (headItems.length > 2) countCycles(rest, cycles + 1) else countCycles(rest, cycles )
}
}
countCycles(item, 0)
}
// Helper to convert ItemDesc into a List[Int] for easier processing
implicit def itemToValueList(item: ItemDesc): List[Int] = List(item.a, item.b, item.c, item.d, item.e, item.f, item.g)
}
case class ItemDesc(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int, g: Int, reason: String)
Output from running:
Item at index 0 has 2 cycles
Item at index 1 has 1 cycles
Item at index 2 has 1 cycles
Item at index 3 has 2 cycles
Item at index 4 has 1 cycles
Hope that helps
As i read, i see that your problem is to treat the case class as a single entity and no as a list of elements and a reason. I would change the case class to one of these alternatives, first one is if the amount of elements is static (4 in this case):
case class ItemDesc(a: Int, b: Int, c: Int, d: Int, reason: String) {
lazy val getAsList = List(a,b,c,d)
}
ItemDesc(1,2,3,4,"reason").getAsList
In the second case, it can be used if the amount of elements is unbounded:
case class ItemDescAlt(reason:String, elements: Int*)
ItemDescAlt("reason", 5164,-5165,-5166,-6195,5165,5166,6195)
And like the rest i will give my custom version for calculate the number of cycles:
def getCycles(list: Seq[Int]): Int = {
def headPositive(list: Seq[Int]): Boolean = {
list.headOption.forall(_ >= 0)
}
val result = list.foldLeft((0, 0, !headPositive(list))) { //we start with a symbol diferent to the firs one
case ((numberOfCycles, cycleLength, lastWasPositive), number) => { //for each element...
val numberSign = number >= 0
val actualCycleLength = if (numberSign == lastWasPositive) { //see if the actual simbol is equal to the last one
cycleLength + 1 //in that case the length is increased
} else {
0 //in the other reset it
}
val actualNCycles = if (actualCycleLength == 2) { //if the actual length is equal to to
numberOfCycles + 1 //it is a proper new cycle
} else {
numberOfCycles // no new cycles
}
(actualNCycles, actualCycleLength, numberSign) //return the actual state
}
}
result._1 //get the final number of cycles
}
If you already have a solution for List, you can convert any case class into a List using productIterator:
scala> case class X(a:Int, b:Int, c:String)
defined class X
scala> val x = X(1,2,"a")
x: X = X(1,2,a)
scala> x.productIterator.toList
res1: List[Any] = List(1, 2, a)
The main problem is that you get back a List[Any] so you might have to do more work to get a List[Int]

Sorting number of lists according to indexes and priority

I have a collection of lists with each containing around 6 to 7 values. Like,
list1 = 2,4,7,4,9,5
list2 = 4,3,7.3,9,8,1.2
list3 = 2,2.4,7,9,8,5
list4 = 9,1.6,4,3,4,1
list5 = 2,5,7,9,1,4
list6 = 6,8,7,2,1,5
list7 = 4,2,5,2,1,3
Now I want to sort these with index1 as primary and index3 as secondary and index2 as tertiary and so on. That is, the output should be like:
2,2.4,7,9,8,5
2,4,7,4,9,5
2,5,7,9,1,4
4,2,5,2,1,3
6,8,7,2,1,5
9,1.6,4,3,4,1
I want the list order to be sorted for index1 first and if the values are same for index1 than sorting is done on index3 and if further same than on index2. Here the number of lists are less which can increase to 20 and the indexes can grow up to 20 as well.
The algorithm I want to know is the same as that of iTunes song sorting, in which songs with the same album are sorted first and then by artist and then by rank and then by name. That's the album's if album names are the same then sorting is done on the artist if same, then by rank and so on. The code can be in C/C++/tcl/shell.
sort -n -t ',' -k 1 -k 3 -k 2
Feed the lists as individual lines into it.
To do this in Tcl, assuming there's not huge amounts of data (a few MB wouldn't be “huge”) the easiest way would be:
# Read the values in from stdin, break into lists of lists
foreach line [split [read stdin] "\n"] {
lappend records [split $line ","]
}
# Sort twice, first by secondary key then by primary (lsort is _stable_)
set records [lsort -index 1 -real $records]
set records [lsort -index 0 -real $records]
# Write the values back out to stdout
foreach record $records {
puts [join $record ","]
}
If you're using anything more complex than simple numbers, consider using the csv package in Tcllib for parsing and formatting, as it will deal with many syntactic issues that crop up in Real Data. If you're dealing with a lot of data (where “lot” depends on how much memory you deploy with) then consider using a more stream-oriented method for handling the data (and there are a few other optimizations in the memory handling) and you might also want to use the -command option to lsort to supply a custom comparator so you can sort only once; the performance hit of a custom comparator is quite high, alas, but for many records the reduced number of comparisons will win out. Or shove the data into a database like SQLite or Postgres.
You can use STL's sort, and then all you have to do is to write a comparison function that does what you want (the example in the link should be good enough).
Since you asked for a Tcl solution:
set lol {
{2 4 7 4 9 5}
{4 3 7.3 9 8 1.2}
{2 2.4 7 9 8 5}
{9 1.6 4 3 4 1}
{2 5 7 9 1 4}
{6 8 7 2 1 5}
{4 2 5 2 1 3}
}
set ::EPS 10e-6
proc compareLists {ixo e1 e2} {
foreach ix $ixo {
set d [expr {[lindex $e1 $ix] - [lindex $e2 $ix]}]
if {abs($d) > $::EPS} {
return [expr {($d>0)-($d<0)}]
}
}
return 0
}
foreach li [lsort -command [list compareLists {0 2 1}] $lol] {
puts $li
}
Hope that helps.
Here is a C++ solution:
#include <iostream>
#include <vector>
#include <algorithm>
template <typename Array, typename CompareOrderIndex>
struct arrayCompare
{
private:
size_t
size ;
CompareOrderIndex
index ;
public:
arrayCompare( CompareOrderIndex idx ) : size( idx.size() ), index(idx) { }
bool helper( const Array &a1, const Array &a2, unsigned int num ) const
{
if( a1[ index[size-num] ] > a2[ index[size-num] ] )
{
return false ;
}
if( !(a1[ index[size-num] ] < a2[ index[size-num] ]) )
{
if( 1 != num )
{
return helper( a1, a2, num-1 ) ;
}
}
return true ;
}
bool operator()( const Array &a1, const Array &a2 ) const
{
return helper( a1, a2, size ) ;
}
} ;
int main()
{
std::vector< std::vector<float> > lists = { { 2, 4, 7, 4, 9, 5},
{ 4, 3, 7.3, 9, 8, 1.2 },
{ 2, 2.4, 7, 9, 8, 5 },
{ 4, 2, 5, 2, 1, 3 },
{ 9, 1.6, 4, 3, 4, 1 },
{ 2, 5, 7, 9, 1, 4 },
{ 6, 8, 7, 2, 1, 5 },
{ 4, 2, 5, 2, 1, 1 },
};
//
// Specify the column indexes to compare and the order to compare.
// In this case it will first compare column 1 then 3 and finally 2.
//
//std::vector<int> indexOrder = { 0, 2, 1, 3, 4 ,5 } ;
std::vector<int> indexOrder = { 0, 2, 1 } ;
arrayCompare< std::vector<float>, std::vector<int>> compV( indexOrder ) ;
std::sort( lists.begin(), lists.end(), arrayCompare< std::vector<float>, std::vector<int>>( indexOrder ) ) ;
for(auto p: lists)
{
for( unsigned int i = 0; i < p.size(); ++i )
{
unsigned int idx = ( i > (indexOrder.size() -1) ? i : indexOrder[i] ) ;
std::cout << p[idx] << ", " ;
}
std::cout << std::endl ;
}
}