Generate dynamic group person - dart

I want make simple application named "Person Group Generator", It will generate group depending on List of person and total group you want create. Example you have 20 list person and want create 10 group from that list, application automatic will generate 10 group and each of group have 2 person. This is how i implement it.
class Person {
final int id;
final String name;
Person({this.id, this.name});
}
List<Person> listPerson = [
Person(id: 1, name: 'Ani'),
Person(id: 2, name: 'Budi'),
Person(id: 3, name: 'Citra'),
Person(id: 4, name: 'Doni'),
Person(id: 5, name: 'Emilia'),
Person(id: 6, name: 'Frasisco'),
Person(id: 7, name: 'Goyu'),
Person(id: 8, name: 'Hani'),
Person(id: 9, name: 'Intan'),
Person(id: 10, name: 'Jeri'),
Person(id: 11, name: 'Karina'),
Person(id: 12, name: 'Lemi'),
Person(id: 13, name: 'Momo'),
Person(id: 14, name: 'Nini'),
Person(id: 15, name: 'Opi'),
Person(id: 16, name: 'Parto'),
Person(id: 17, name: 'Queen'),
Person(id: 18, name: 'Risa'),
Person(id: 19, name: 'Sisca'),
Person(id: 20, name: 'Toni'),
// Person(id: 21, name: 'Ucok'),
// Person(id: 22, name: 'Vani'),
// Person(id: 23, name: 'Wahyu'),
// Person(id: 24, name: 'Xixi'),
];
Map<String, List<Person>> generateGroup(
List<Person> values, {
int generateTotalGroup = 1,
}) {
var tempMap = <String, List<Person>>{};
var tempPersonList = <Person>[];
var totalPersonEveryGroup = 0.0;
final totalPerson = values.length;
values.shuffle();
if (totalPerson % generateTotalGroup == 0) {
totalPersonEveryGroup = values.length / generateTotalGroup;
for (int i = 1; i <= generateTotalGroup; i++) {
var nameGroup = "Group $i";
var selectedPerson = values
.getRange(tempPersonList.length,
tempPersonList.length + totalPersonEveryGroup.toInt())
.toList();
tempMap[nameGroup] = selectedPerson;
tempPersonList = [...tempPersonList, ...selectedPerson];
}
} else {
/// Question to StackOverflow
}
return tempMap;
}
void main() {
final result = generateGroup(listPerson, generateTotalGroup: 10);
result.forEach((key,listPerson){
listPerson.forEach((person){
print('key $key || person ${person.name}');
});
});
}
Output
key Group 1 || person Emilia
key Group 1 || person Nini
key Group 2 || person Citra
key Group 2 || person Hani
key Group 3 || person Frasisco
key Group 3 || person Queen
key Group 4 || person Goyu
key Group 4 || person Risa
key Group 5 || person Karina
key Group 5 || person Intan
key Group 6 || person Lemi
key Group 6 || person Ani
key Group 7 || person Parto
key Group 7 || person Doni
key Group 8 || person Budi
key Group 8 || person Toni
key Group 9 || person Momo
key Group 9 || person Jeri
key Group 10 || person Sisca
key Group 10 || person Opi
If total person can be divided by total group needed is fine (20 person / 10 group = 2 person every group) , application result is what i expected.But the problem is when is can't be divided, i don't know how to handle it.
Example total person = 24 and total group needed = 10, If i divided it will result 2.4. What i expected if result can't be divided is like this :
Expectation
key Group 1 || person Ani
key Group 1 || person Budi
key Group 1 || person Citra
key Group 2 || person Doni
key Group 2 || person Emilia
key Group 2 || person Frasisco
key Group 3 || person Goyu
key Group 3 || person Hani
key Group 3 || person Intan
key Group 4 || person Jeri
key Group 4 || person Karina
key Group 4 || person Lemi
key Group 5 || person Momo
key Group 5 || person Nini
key Group 6 || person Opi
key Group 6 || person Parto
key Group 7 || person Queen
key Group 7 || person Risa
key Group 8 || person Sisca
key Group 8 || person Toni
key Group 9 || person Ucok
key Group 9 || person Vani
key Group 10 || person Wahyu
key Group 10 || person Xixi
How can i make like above if total person can't be divided by total group neeeded ?
Thank's

Try something like that:
class Person {
final int id;
final String name;
Person({this.id, this.name});
}
List<Person> listPerson = [
Person(id: 1, name: 'Ani'),
Person(id: 2, name: 'Budi'),
Person(id: 3, name: 'Citra'),
Person(id: 4, name: 'Doni'),
Person(id: 5, name: 'Emilia'),
Person(id: 6, name: 'Frasisco'),
Person(id: 7, name: 'Goyu'),
Person(id: 8, name: 'Hani'),
Person(id: 9, name: 'Intan'),
Person(id: 10, name: 'Jeri'),
Person(id: 11, name: 'Karina'),
Person(id: 12, name: 'Lemi'),
Person(id: 13, name: 'Momo'),
Person(id: 14, name: 'Nini'),
Person(id: 15, name: 'Opi'),
Person(id: 16, name: 'Parto'),
Person(id: 17, name: 'Queen'),
Person(id: 18, name: 'Risa'),
Person(id: 19, name: 'Sisca'),
Person(id: 20, name: 'Toni'),
Person(id: 21, name: 'Ucok'),
Person(id: 22, name: 'Vani'),
Person(id: 23, name: 'Wahyu'),
Person(id: 24, name: 'Xixi'),
];
Map<String, List<Person>> generateGroup(
List<Person> values, {
int generateTotalGroup = 1,
}) {
var tempMap = <String, List<Person>>{};
var tempPersonList = <Person>[];
var totalPersonEveryGroup = 0;
final totalPerson = values.length;
values.shuffle();
var extra = totalPerson % generateTotalGroup;
totalPersonEveryGroup = values.length ~/ generateTotalGroup;
for (int i = 1; i <= generateTotalGroup; i++) {
var end = totalPersonEveryGroup;
if (extra > 0) {
extra--;
end++;
}
var nameGroup = "Group $i";
var selectedPerson = values
.getRange(tempPersonList.length,
tempPersonList.length + end)
.toList();
tempMap[nameGroup] = selectedPerson;
tempPersonList = [...tempPersonList, ...selectedPerson];
}
return tempMap;
}
void main() {
final result = generateGroup(listPerson, generateTotalGroup: 10);
result.forEach((key,listPerson){
listPerson.forEach((person){
print('key $key || person ${person.name}');
});
});
}

The easiest way to distribute n elements into k buckets is round-robin.
List<List<T>> distribute<T>(List<T> elements, int buckets) {
var result = [for (var i = 0; i < buckets; i++) <T>[]];
for (var i = 0, b = 0; i < elements.length; i++) {
result[b].add(elements[i]);
b = b + 1;
if (b == buckets) b = 0;
}
return result;
}
That will not give you the results you ask for, where the first elements are kept together. Instead it will spread the first bucket-count elements into each their own bucket, then add the next bucket-count elements to the same buckets, etc.
If you want to keep the elements together, I'd do something slightly more complicated:
List<List<T>> split<T>(List<T> elements, int buckets) {
var n = elements.length;
var min = n ~/ buckets;
var remainder = n.remainder(buckets); // Number of buckets with one more element.
var i = 0;
return [
for (var b = 0; b < buckets; b++) [
for (var j = 0; j < min; j++) elements[i++],
if (--remainder >= 0) elements[i++]
]
];
}

Related

Inserting words into a table

So, i have a script where i am inputting 3 words in a string and putting them into a small table and i only need this script to print a new table i can copy and paste, so i just need to print what the table would look like this is the script currently have
local tbl = {
{1, "", 0},
{2, "", 0},
{3, "", 0}
}
local input = "i hate debugging"
local words = {}
x = 0
repeat
x = x + 1
for i, v in ipairs(tbl) do
if tonumber(v[1]) == x then
for word in input:gmatch"[^ ,\r\n]+" do
table.insert(words, word)
end
end
end
until x == 1
and the desired output should look like this
{1, "i", 0},
{2, "hate", 0},
{3, "debugging", 0},
The question isn't very clear, and OP goal is not clear, but it seems that you may want something like this:
local tbl = {
{ 1, "", 0 },
{ 2, "", 0 },
{ 3, "", 0 }
}
local input = "i hate debugging"
local nextWord = input:gmatch"[^ ,\r\n]+"
for k, t in ipairs(tbl) do
t[2] = nextWord() or ""
end
-- Display updated `tbl`
print("updated tbl")
for k, v in ipairs(tbl) do
print(string.format('{ %d, "%s", %d },', v[1], v[2], v[3]))
end
gmatch returns an iterator, so you can just call this iterator repeatedly to get successive matches. You can loop over tbl, calling the iterator each time to set the string. When the iterator is out of matches it will return nil, so the code sets the string to "" when the iterator is exhausted.
Program output:
updated tbl
{ 1, "i", 0 },
{ 2, "hate", 0 },
{ 3, "debugging", 0 },
Creating A New Table From Input
OP has clarified in a comment that a new table should be created from the input. Here is a function createWordTable that creates and returns a fresh table from a string of words. The printWordTable function is just a utility function to show the contents of a word table.
function createWordTable(wordString)
local wordTbl = {}
local i = 1
for w in wordString:gmatch"[^ ,\r\n]+" do
wordTbl[i] = { i, w, 0 }
i = i + 1
end
return wordTbl
end
function printWordTable(wordTbl)
for k, v in ipairs(wordTbl) do
print(string.format('{ %d, %s, %d }', v[1], v[2], v[3]))
end
end
Sample interaction:
> wtbl = createWordTable("one, two, three")
> printWordTable(wtbl)
{ 1, one, 0 }
{ 2, two, 0 }
{ 3, three, 0 }
> wtbl = createWordTable("one, two, three, four, five")
> printWordTable(wtbl)
{ 1, one, 0 }
{ 2, two, 0 }
{ 3, three, 0 }
{ 4, four, 0 }
{ 5, five, 0 }

Print the second largest number on the list

I need to print the second largest number on the list, the output from the below code is all elements in the list except the first and the last one.
What is the mistake?
void main () {
List a = [9,6,4,10,13,2,3,5];
a.sort;
for(int x in a){
for (int max in a){
for (int second_last in a){
if (x > max) {
second_last = max;
max = x;
} else if (x > second_last && x != max) {
second_last = x;
print(second_last);
}
}
}
}
}
There are a few things wrong with your code:
You're not actually sorting the list. The sort method returns a new sorted list, it doesn't sort the existing list. So you need to do:
a = a.sort;
You're iterating over the list 3 times when you only need to iterate over it once.
You're not keeping track of the second largest number, you're just printing it out as you find it.
You're not checking for duplicates. If there are duplicate numbers in the list, your code will print them out multiple times.
Here's a corrected pseudo-code
void main() {
List a = [9, 6, 4, 10, 13, 2, 3, 5];
a.sort;
int max = a[0];
int second_last = a[0];
for (int x in a) {
if (x > max) {
second_last = max;
max = x;
} else if (x > second_last && x != max) {
second_last = x;
}
}
print(second_last);
}
I need to print the second largest number on the list
Sort the array (desc).
Access the second element.
List a = [9, 6, 4, 10, 13, 2, 3, 5];
a.sort((a, z) => z - a);
// final b = a.toList()..sort(...); if you do not want to modify the original array.
print(a.take(2)); // [13, 10]
print(a.take(2)[1]); // [10]
print(a.take(2).skip(1)); // [10]
print(a.skip(1).first); // [10]
You are missing () on sort. You can do
void main() {
List a = [9, 6, 4, 10, 13, 2, 3, 5];
a.sort();
print(a[a.length - 2]); //get second large item
List b = [9, 6, 4, 10, 13, 2, 3, 5];
//or like revese sort
b.sort((a, b) => b.compareTo(a));
print(b[1]);
}
If you find a solution that is without using the sort function, and also works with all possible conditions,
so you can use this solution as well,
void main(){
var list =[9,6,4,10,13,2,3,5,13];
var secondLargest = findSecLargest(list);
print(secondLargest);
}
findSecLargest(List<int> list) {
var secLargest =-1;
var largest=list[0];
for(int i = 1 ; i < list.length ; i ++){
if(largest<list[i]){
secLargest = largest;
largest = list[i];
}else if(secLargest<list[i] && list[i]!=largest){
secLargest = list[i];
}
}
return secLargest;
}

General insertion sort algorithm not moving the first object in list

I need to create a general insertion sort algorithm using move semantics. I have it working for entire lists of different types of objects except for the very first object in the list.
template<typename Iter, typename Comparator>
void insertionSort(const Iter& begin, const Iter& end, Comparator compareFn)
{
for (auto i = begin + 1; i < end; i++)
{
auto currentthing = std::move(*i);
auto j = std::move(i - 1);
while (j >= begin and compareFn(*j, currentthing))
{
*(j + 1) = std::move(*j);
if (j == begin)
break;
j--;
}
*(j + 1) = std::move(currentthing);
}
}
Where comparing a list of strings from my main function:
int main()
{
vector<int> numbers = { 0, 1, 8, 4, 2, 9, 5, 3, 6, 7, 10 };
insertionSort(numbers.begin(), numbers.end(), std::less<int>());
cout << "Sorted: " << numbers << "\n";
vector<string> names = { "p", "a", "b", "d", "c", "f", "e" };
insertionSort(names.begin(), names.end(), std::greater<string>());
cout << "Sorted: " << names << "\n";
return 0;
}
Outputs the following
Sorted: [ 0 10 9 8 7 6 5 4 3 2 1 ]
Sorted: [ a b c d e f ]
The while loop should break when j equals i and not when j equals begin. So, the following:
if (j == begin)
break;
should actually be:
if (j == i)
break;

how do I make an integer to roman algorithm in dart?

I want to write an algorithm that converts integer numbers to roman numbers and supports any positive number in dart.
I can do this in Java using String builder and i tried to do it in dart but i failed.
so please if anyone could help me, that would be very much appreciated!
here is the java algorithm, maybe it would help:
public static int[] arabianRomanNumbers = new int[]{
1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1
};
public static String[] romanNumbers = new String[]{
"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"
};
public String intToRoman(int num) {
if (num < 0) return "";
else if (num == 0) return "nulla";
StringBuilder builder = new StringBuilder();
for (int a = 0; a < arabianRomanNumbers.length; a++) {
int times = num / arabianRomanNumbers[a]; // equals 1 only when arabianRomanNumbers[a] = num
// executes n times where n is the number of times you have to add
// the current roman number value to reach current num.
builder.append(romanNumbers[a].repeat(times));
num -= times * arabianRomanNumbers[a]; // subtract previous roman number value from num
}
return builder.toString();
}
StringBuilder is called StringBuffer in Dart and does nearly the same but with a little different interface which you can read more about in the API documentation:
https://api.dart.dev/stable/2.7.1/dart-core/StringBuffer-class.html
With this knowledge, I have converted your Java code into Dart:
const List<int> arabianRomanNumbers = [
1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1
];
const List<String> romanNumbers = [
"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"
];
String intToRoman(int input) {
var num = input;
if (num < 0) {
return "";
}
else if (num == 0) {
return "nulla";
}
final builder = StringBuffer();
for (var a = 0; a < arabianRomanNumbers.length; a++) {
final times = (num / arabianRomanNumbers[a]).truncate(); // equals 1 only when arabianRomanNumbers[a] = num
// executes n times where n is the number of times you have to add
// the current roman number value to reach current num.
builder.write(romanNumbers[a] * times);
num -= times * arabianRomanNumbers[a]; // subtract previous roman number value from num
}
return builder.toString();
}
void main() {
for (var i = 0; i <= 1000; i++) {
print('$i => ${intToRoman(i)}');
}
}

Remove specific entry from Lua table

I am inserting into a table like this
Admin = {}
table.insert(Admins, {id = playerId, Count = 0})
And that works fine.
How do I remove that specific admin from that table now?
The following does not work, and Im sure its because ID is stored in an array that's inside of the table, but how would I access that then?
table.remove(Admins, playerId)
Basically,
I want to remove from the table Admins, where the ID == playerId that I input.
There are two approaches to remove an entry from the table, both are acceptable ways:
1. myTable[index] = nil Removes an entry from given index, but adds a hole in the table by maintaining the indices
local Admins = {}
table.insert(Admins, {id = 10, Count = 0})
table.insert(Admins, {id = 20, Count = 1})
table.insert(Admins, {id = 30, Count = 2})
table.insert(Admins, {id = 40, Count = 3})
local function removebyKey(tab, val)
for i, v in ipairs (tab) do
if (v.id == val) then
tab[i] = nil
end
end
end
-- Before
-- [1] = {['Count'] = 0, ['id'] = 10},
-- [2] = {['Count'] = 1, ['id'] = 20},
-- [3] = {['Count'] = 2, ['id'] = 30},
-- [4] = {['Count'] = 3, ['id'] = 40}}
removebyKey(Admins, 20)
-- After
-- [1] = {['Count'] = 0, ['id'] = 10},
-- [3] = {['Count'] = 2, ['id'] = 30},
-- [4] = {['Count'] = 3, ['id'] = 40}
2. table.remove(myTable, index)
Removes the entry from given index and renumbering the indices
local function getIndex(tab, val)
local index = nil
for i, v in ipairs (tab) do
if (v.id == val) then
index = i
end
end
return index
end
local idx = getIndex(Admins, 20) -- id = 20 found at idx = 2
if idx == nil then
print("Key does not exist")
else
table.remove(Admins, idx) -- remove Table[2] and shift remaining entries
end
-- Before is same as above
-- After entry is removed. Table indices are changed
-- [1] = {['id'] = 10, ['Count'] = 0},
-- [2] = {['id'] = 30, ['Count'] = 2},
-- [3] = {['id'] = 40, ['Count'] = 3}

Resources