How to best arrange students into different groups? - algorithm

Problem:
We have 370 students in 31 groups, each student is interested in 1 subject (subject 1 to 6)
We have 4 classrooms, each classroom can accommodate fixed number of students with fixed number of subjects.
How can we best arrange those students into all classrooms so that they can all have their favourite subjects? If that's not possible, return the best option where each classroom accommodates the highest matching percentage.
Given that all students in the same group must go together.
Example:
Students:
{
'G1': [ { '6': 9 }, 9 ],
'G2': [ { '6': 7 }, 7 ],
'G3': [ { '1': 1, '2': 1 }, 2 ],
'G4': [ { '6': 4 }, 4 ],
'G5': [ { '6': 2 }, 2 ],
'G6': [ { '1': 1, '6': 5 }, 6 ],
'G7': [ { '6': 3 }, 3 ],
'G8': [ { '6': 2 }, 2 ],
'G9': [ { '1': 2, '2': 1 }, 3 ],
'G10': [ { '1': 2, '2': 6, '3': 3, '4': 2 }, 13 ],
'G11': [ { '6': 13 }, 13 ],
'G12': [ { '4': 1, '6': 8 }, 9 ],
'G13': [ { '1': 5, '2': 5, '3': 12, '4': 6 }, 28 ],
'G14': [ { '3': 9, '4': 3, '6': 8 }, 20 ],
'G15': [ { '2': 4, '3': 10, '4': 2, '6': 3 }, 19 ],
'G16': [ { '3': 9, '4': 8, '5': 1, '6': 5 }, 23 ],
'G17': [ { '2': 2, '3': 3, '6': 19 }, 24 ],
'G18': [ { '1': 2, '2': 1, '3': 3, '4': 11, '5': 2, '6': 2 }, 21 ],
'G19': [ { '1': 2, '2': 4, '3': 6, '4': 4, '5': 1, '6': 3 }, 20 ],
'G29': [ { '2': 3, '3': 13, '5': 1, '6': 6 }, 23 ],
'G21': [ { '1': 1, '2': 2, '3': 11, '4': 1, '6': 10 }, 25 ],
'G22': [ { '3': 1, '6': 3 }, 4 ],
'G23': [ { '3': 1, '4': 1 }, 2 ],
'G24': [ { '6': 6 }, 6 ],
'G25': [ { '2': 1 }, 1 ],
'G26': [ { '2': 3, '3': 4, '4': 14, '5': 2, '6': 5 }, 28 ],
'G27': [ { '1': 3, '2': 2, '3': 3, '5': 3, '6': 12 }, 23 ],
'G28': [ { '6': 8 }, 8 ],
'G29': [ { '2': 3, '3': 5, '4': 5, '5': 3, '6': 1 }, 17 ],
'G30': [ { '2': 2, '3': 1, '6': 1 }, 4 ],
'G31': [ { '6': 1 }, 1 ]
}
Classrooms:
{
'1B': [ { '3': 9, '4': 19, '5': 1, '6': 71 }, 100 ],
'1A': [ { '1': 11, '2': 19, '3': 33, '4': 1, '6': 16 }, 80 ],
'2B': [ { '2': 3, '3': 14, '4': 38, '5': 12, '6': 43 }, 110 ],
'2A': [ { '1': 8, '2': 18, '3': 38, '6': 16 }, 80 ]
}
Brute force seems not possible because the real problem can contain up to 1500 students.

I think you could use simulated annealing to find some optimal solution and use iou for metric.
I try to do it and not a perfect solution (mean IOU is equal to 0.8079440721):
{'G1': '2B', 'G2': '1B', 'G3': '1A', 'G4': '1B', 'G5': '1B', 'G6': '2B', 'G7': '1B', 'G8': '1B', 'G9': '2A', 'G10': '1A', 'G11': '1B', 'G12': '1B', 'G13': '2A', 'G14': '1A', 'G15': '1A', 'G16': '1B', 'G17': '1B', 'G18': '2B', 'G19': '1A', 'G20': '2A', 'G21': '2A', 'G22': '2B', 'G23': '1A', 'G24': '2B', 'G25': '2A', 'G26': '2B', 'G27': '2B', 'G28': '1B', 'G29': '2B', 'G30': '1A', 'G31': '1A'}
1B {'2': 2, '3': 12, '4': 9, '5': 1, '6': 71}
1A {'1': 5, '2': 17, '3': 30, '4': 12, '5': 1, '6': 16}
2B {'1': 6, '2': 9, '3': 16, '4': 30, '5': 10, '6': 43}
2A {'1': 8, '2': 12, '3': 36, '4': 7, '5': 1, '6': 16}
iou for 1B = 0.8571428571428571
iou for 1A = 0.75
iou for 2B = 0.8064516129032258
iou for 2A = 0.8181818181818182

Related

Riot API - How can I have summoners roles on a current game

I'm currently developing a live game analysis system similar to op.gg, u.gg or porofessor.gg and I'm not able to get the summoners roles (individualPosition) with the SUMMONER_V4 endpoint. This infos can be retrieved from MATCH_V4 and MATCH_V5 but not in current game only on post games.
Do you have a solution ?
1 summoner from SUMMONER_V4
{
"teamId": 100,
"spell1Id": 4,
"spell2Id": 12,
"championId": 134,
"profileIconId": 29,
"summonerName": "ZWYRØØ",
"bot": false,
"summonerId": "AMNq5HI58rERnuyXFIG59jefC50DedqayUTkovUa2Vyf4yc",
"gameCustomizationObjects": [],
"perks": {
"perkIds": [
8112,
8139,
8138,
8135,
8232,
8226,
5005,
5008,
5003
],
"perkStyle": 8100,
"perkSubStyle": 8200
}
}
1 summoner from MATCH_V5
{
"assists": 11,
"baronKills": 0,
"bountyLevel": 4,
"champExperience": 16132,
"champLevel": 16,
"championId": 92,
"championName": "Riven",
"championTransform": 0,
"consumablesPurchased": 7,
"damageDealtToBuildings": 4623,
"damageDealtToObjectives": 6137,
"damageDealtToTurrets": 4623,
"damageSelfMitigated": 29549,
"deaths": 5,
"detectorWardsPlaced": 3,
"doubleKills": 3,
"dragonKills": 0,
"firstBloodAssist": false,
"firstBloodKill": true,
"firstTowerAssist": false,
"firstTowerKill": false,
"gameEndedInEarlySurrender": false,
"gameEndedInSurrender": false,
"goldEarned": 14587,
"goldSpent": 14205,
"individualPosition": "TOP",
"inhibitorKills": 1,
"inhibitorTakedowns": 1,
"inhibitorsLost": 0,
"item0": 6630,
"item1": 2055,
"item2": 6035,
"item3": 3071,
"item4": 3044,
"item5": 3158,
"item6": 3364,
"itemsPurchased": 27,
"killingSprees": 4,
"kills": 15,
"lane": "TOP",
"largestCriticalStrike": 0,
"largestKillingSpree": 4,
"largestMultiKill": 3,
"longestTimeSpentLiving": 487,
"magicDamageDealt": 0,
"magicDamageDealtToChampions": 0,
"magicDamageTaken": 9753,
"neutralMinionsKilled": 9,
"nexusKills": 1,
"nexusLost": 0,
"nexusTakedowns": 1,
"objectivesStolen": 0,
"objectivesStolenAssists": 0,
"participantId": 1,
"pentaKills": 0,
"perks": {
"statPerks": {
"defense": 5002,
"flex": 5008,
"offense": 5008
},
"styles": [
{
"description": "primaryStyle",
"selections": [
{
"perk": 8010,
"var1": 720,
"var2": 0,
"var3": 0
},
{
"perk": 9111,
"var1": 2616,
"var2": 520,
"var3": 0
},
{
"perk": 9104,
"var1": 12,
"var2": 30,
"var3": 0
},
{
"perk": 8299,
"var1": 1072,
"var2": 0,
"var3": 0
}
],
"style": 8000
},
{
"description": "subStyle",
"selections": [
{
"perk": 8236,
"var1": 14,
"var2": 0,
"var3": 0
},
{
"perk": 8210,
"var1": 15,
"var2": 0,
"var3": 0
}
],
"style": 8200
}
]
},
"physicalDamageDealt": 122017,
"physicalDamageDealtToChampions": 27842,
"physicalDamageTaken": 17221,
"profileIcon": 4982,
"puuid": "ntuHEb-brsQY_ecD0_RJWuM7aksXwMdaK2q16TQ3vvJ_F11cOUtg_kwhGQ-Ihn4wDSu7WPuQipJn3Q",
"quadraKills": 0,
"riotIdName": "",
"riotIdTagline": "",
"role": "DUO",
"sightWardsBoughtInGame": 0,
"spell1Casts": 397,
"spell2Casts": 71,
"spell3Casts": 142,
"spell4Casts": 34,
"summoner1Casts": 4,
"summoner1Id": 4,
"summoner2Casts": 7,
"summoner2Id": 14,
"summonerId": "ZVUXWayHZDCDR5V67fUp14i3vsZNMmqIjmppq2XJepptJ7Y-",
"summonerLevel": 40,
"summonerName": "ojdfviys",
"teamEarlySurrendered": false,
"teamId": 100,
"teamPosition": "TOP",
"timeCCingOthers": 35,
"timePlayed": 1719,
"totalDamageDealt": 123497,
"totalDamageDealtToChampions": 29232,
"totalDamageShieldedOnTeammates": 0,
"totalDamageTaken": 28681,
"totalHeal": 6272,
"totalHealsOnTeammates": 0,
"totalMinionsKilled": 160,
"totalTimeCCDealt": 107,
"totalTimeSpentDead": 183,
"totalUnitsHealed": 1,
"tripleKills": 1,
"trueDamageDealt": 1480,
"trueDamageDealtToChampions": 1390,
"trueDamageTaken": 1706,
"turretKills": 2,
"turretTakedowns": 4,
"turretsLost": 5,
"unrealKills": 0,
"visionScore": 22,
"visionWardsBoughtInGame": 5,
"wardsKilled": 2,
"wardsPlaced": 6,
"win": true
}
Thanks by advance

How to covert Laravel's collection to array object collection?

I have small laravel collection as below.
[
{
id: 1,
data1: 11,
data2: 12,
data3: 13,
created_at: null,
updated_at: null
},
{
id: 2,
data1: 14,
data2: 15,
data3: 16,
created_at: null,
updated_at: null
}
]
But I would like to convert to array collection like below.
{
data: [
[
11,
12,
13
],
[
14,
15,
16
]
]
}
Appreciated for advice and so sorry for my English. Thank you very much.
Use toArray() which converts this object into an array.
$data->toArray();
Now the collection converted into an array and looks like:-
[
[
id: 1,
data1: 11,
data2: 12,
data3: 13,
created_at: null,
updated_at: null
],
[
id: 2,
data1: 14,
data2: 15,
data3: 16,
created_at: null,
updated_at: null
]
]
But as per your requirements, you don't want associative index for the array, So use
$data = array_values($data);
Now your keys has been removed and final data is:-
[
[
11,
12,
13
],
[
14,
15,
16
]
]

AmCharts - Controlling value axis labels

I want my y-axis to have labels 0%, 25%, 50%, 75%, 100%
I would have expected a gridCount of 4 or 5 to do it, but it refuses. I've tried labelFrequency set to 25 but that doesn't work either.
window.AmCharts.makeChart('chartdiv', {
'type': 'serial',
'categoryField': 'category',
'dataDateFormat': 'YYYY-MM-DD',
'startDuration': 1,
'theme': 'light',
'categoryAxis': {
'parseDates': true,
'axisThickness': 0,
'color': '#989898',
'gridThickness': 0
},
'graphs': [
{
'fillAlphas': 1,
'type': 'column',
'valueField': 'column-1'
}
],
'valueAxes': [
{
'zeroGridAlpha': -2,
'titleColor': '#989898',
'axisThickness': 0,
'color': '#989898',
'gridThickness': 1,
unit: '%',
autoGridCount: false,
minimum:0,
maximum:100,
gridCount: 5
}
],
'dataProvider': [
{
'category': '2014-03-01',
'column-1': 8
},
{
'category': '2014-03-02',
'column-1': 16
},
{
'category': '2014-03-03',
'column-1': 2
},
{
'category': '2014-03-04',
'column-1': 7
},
{
'category': '2014-03-05',
'column-1': 5
},
{
'category': '2014-03-06',
'column-1': 9
},
{
'category': '2014-03-07',
'column-1': 4
},
{
'category': '2014-03-08',
'column-1': 15
},
{
'category': '2014-03-09',
'column-1': 12
},
{
'category': '2014-03-10',
'column-1': 17
},
{
'category': '2014-03-11',
'column-1': 18
},
{
'category': '2014-03-12',
'column-1': 21
},
{
'category': '2014-03-13',
'column-1': 24
},
{
'category': '2014-03-14',
'column-1': 23
},
{
'category': '2014-03-15',
'column-1': 24
}
]
})
Unfortunately there isn't a way to outright set your own axis divisions through the value axis properties. To workaround this, you can disable the value axis labels and grids and set up your own grid and labels using guides:
'valueAxes': [{
'zeroGridAlpha': -2,
'titleColor': '#989898',
'axisThickness': 0,
'color': '#989898',
'gridThickness': 1,
minimum: 0,
maximum: 100,
gridAlpha: 0,
tickLength: 0,
labelsEnabled: false,
guides: [{
value: 0,
label: "0%",
tickLength: 5,
lineAlpha: .15
}, {
value: 25,
label: "25%",
tickLength: 5,
lineAlpha: .15
}, {
value: 50,
label: "50%",
tickLength: 5,
lineAlpha: .15
}, {
value: 75,
label: "75%",
tickLength: 5,
lineAlpha: .15
}, {
value: 100,
label: "100%",
tickLength: 5,
lineAlpha: .15
},
]
}],
Demo below:
AmCharts.makeChart('chartdiv', {
'type': 'serial',
'categoryField': 'category',
'dataDateFormat': 'YYYY-MM-DD',
'startDuration': 1,
'theme': 'light',
'categoryAxis': {
'parseDates': true,
'axisThickness': 0,
'color': '#989898',
'gridThickness': 0
},
'graphs': [{
'fillAlphas': 1,
'type': 'column',
'valueField': 'column-1'
}],
'valueAxes': [{
'zeroGridAlpha': -2,
'titleColor': '#989898',
'axisThickness': 0,
'color': '#989898',
'gridThickness': 1,
minimum: 0,
maximum: 100,
gridAlpha: 0,
tickLength: 0,
labelsEnabled: false,
guides: [{
value: 0,
label: "0%",
tickLength: 5,
lineAlpha: .15
}, {
value: 25,
label: "25%",
tickLength: 5,
lineAlpha: .15
}, {
value: 50,
label: "50%",
tickLength: 5,
lineAlpha: .15
}, {
value: 75,
label: "75%",
tickLength: 5,
lineAlpha: .15
}, {
value: 100,
label: "100%",
tickLength: 5,
lineAlpha: .15
},
]
}],
'dataProvider': [{
'category': '2014-03-01',
'column-1': 8
},
{
'category': '2014-03-02',
'column-1': 16
},
{
'category': '2014-03-03',
'column-1': 2
},
{
'category': '2014-03-04',
'column-1': 7
},
{
'category': '2014-03-05',
'column-1': 5
},
{
'category': '2014-03-06',
'column-1': 9
},
{
'category': '2014-03-07',
'column-1': 4
},
{
'category': '2014-03-08',
'column-1': 15
},
{
'category': '2014-03-09',
'column-1': 12
},
{
'category': '2014-03-10',
'column-1': 17
},
{
'category': '2014-03-11',
'column-1': 18
},
{
'category': '2014-03-12',
'column-1': 21
},
{
'category': '2014-03-13',
'column-1': 24
},
{
'category': '2014-03-14',
'column-1': 23
},
{
'category': '2014-03-15',
'column-1': 24
}
]
})
<script src="//www.amcharts.com/lib/3/amcharts.js"></script>
<script src="//www.amcharts.com/lib/3/serial.js"></script>
<div id="chartdiv" style="width: 100%; height: 400px;"></div>

Datatable scroll x issue using fixedColumn

im using jquery datatables with fixedColumns. Everything working fine but im having an issue with scroll x.
As u can see, i cant remove the scroll x from fixed column. Any ideas to solve this? Initialization:
$(document).ready(function(){
var oTable = $('#matriz').dataTable({
"bStateSave": true,
"iCookieDuration": 60*60*24*30*365,
"sDom": 'TC<"clear">lfrtip',
"oTableTools": {
"sSwfPath": "//cdn.datatables.net/tabletools/2.2.2/swf/copy_csv_xls_pdf.swf",
"aButtons": [
{
"sExtends": "xls",
"sButtonText": "Excel",
"mColumns":
[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22
]
}
]
},
"aoColumnDefs": [
{ 'bSortable': false, 'aTargets':
[
8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23
]
}
],
"pagingType": "full_numbers",
"oLanguage": {
"sInfo": "Exibindo de _START_ até _END_. Resultados encontrados: _TOTAL_",
"sSearch": "Pesquisar: ",
"sEmptyTable": "Não existem solicitações para exibir.",
"sLengthMenu": "Visualizar _MENU_ solicitações",
"oPaginate": {
"sFirst": "Primeira",
"sLast": "Última",
"sNext": "Próxima",
"sPrevious": "Anterior"
}
},
"oColVis": {
"buttonText": "Ocultar colunas",
"bRestore": true,
"aiExclude": [ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 23 ],
"sRestore": 'Restaurar'
},
"lengthMenu": [[10, 25, 50, 100, -1], [10, 25, 50, 100, "Todas"]],
"iDisplayLength": 10,
scrollY: 325,
"sScrollX": "100%",
scrollCollapse: true,
fixedColumns: {
leftColumns: 1
}
});
setTimeout(function (){
oTable.fnAdjustColumnSizing();
}, 10 );
});
Adding overflow-x:hidden to the DTFC_LeftBodyLiner div seems to fix the display issue.

Merging and updating hash keys in Redis with Ruby

I have a list the following hashes:
{
key_main1: {
k1: 1,
k2: 11,
k3: 33,
k4: 146,
k5: 12,
# etc
},
key_main2: {
k1: 1,
k2: 11,
k3: 33,
k4: 146,
k5: 12,
# etc
},
# etc
}
which is save in a redis as json:
redis_key1 = "redis_key1"
redis.set("redis_key", my_hash.to_json)
redis.get("redis_key") # =>
"{"key_main":{"k1":1,"k2":11,"k3":33,"k4":146,"k5":12}}"
The hashes have the same structure but can have different keys. On each iteration I want to update the existing keys by summing up the values of "k"s or/and insert the keys that don't exist:
So the second hash in the list looks like this
{
key_main1: {
k3: 44,
k4: 14,
k18: 99
},
key_main3: {
k2: 77
}
}
Then after the seconds iteration the result in Redis will look like the following:
{
key_main1: {
k1: 1,
k2: 11,
k3: 33,
k4: 160,
k5: 12,
k18: 99
},
key_main2: {
k1: 1,
k2: 11,
k3: 33,
k4: 146,
k5: 12
},
key_main3: {
k2: 77
}
}
What's the easiest and best way to do it? Do I have to parse (restore)json in each iteration in order to check if the keys exist and update or insert them?
The best way is to parse the JSON back into a hash, otherwise you will have a really hard time figuring out how to combine the hashes.
To combine them, the best and easiest is with Hash#merge:
h1 = { m1: { k1: 10, k2: 20, k3: 30 }, m2: { k1: 11, k2: 12 } }
h2 = { m1: { k1: 500, k2: 5, k4: 40 }, m3: { k2: 123 } }
pp h1.merge(h2) { |key, v1, v2|
v1.merge(v2) { |key, v1, v2| v1 + v2 }
}
=> { :m1 => { :k1 => 510,:k2 => 25, :k3 => 30, :k4 => 40 },
:m2 => { :k1 => 11, :k2 => 12},
:m3 => { :k2 => 123 } }
This code assumes the keys in h1 and h2 always contain a hash with integer keys.

Resources