Redesign the algorithm to choose wrongly sorted elements
- When checking the order the first time, elements above are preferred marked as wrong. - When the user corrects his solution, the newest inserted elements are preferred marked as wrong. This affects only cases, where there are multiple options for the same number of correct elements. In general, the algorithm minimizes the number of elements it needs to mark as wrong. Closes #5
This commit is contained in:
parent
fc7f630001
commit
099cc72429
93
quiz.js
93
quiz.js
@ -133,47 +133,52 @@ function shuffle_cards(section) {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
function choose_incorrects(idx_vals) {
|
function choose_incorrects(elems) {
|
||||||
let options = {
|
let options = {
|
||||||
0: [],
|
"-1": [],
|
||||||
};
|
};
|
||||||
function find_longest_chain(maxkey) {
|
function chain_is_better(old_chain, new_chain) {
|
||||||
let longest = null;
|
if (old_chain == null) {
|
||||||
for (let key in options) {
|
return true;
|
||||||
if (
|
} else if (new_chain.length > old_chain.length) {
|
||||||
(
|
return true;
|
||||||
maxkey == null
|
} else if (new_chain.length < old_chain.length) {
|
||||||
|| key <= maxkey
|
return false;
|
||||||
)
|
}
|
||||||
&& (
|
let old_nums = old_chain.map(elem => elem[1]).sort((a, b) => a - b).reverse();
|
||||||
longest == null
|
let new_nums = new_chain.map(elem => elem[1]).sort((a, b) => a - b).reverse();
|
||||||
|| options[key].length > options[longest].length
|
for (let i=0; i<old_nums.length; i++) {
|
||||||
|| (
|
if (new_nums[i] < old_nums[i]) {
|
||||||
options[key].length == options[longest].length
|
return true;
|
||||||
&& Number.parseInt(key) < Number.parseInt(longest)
|
} else if (new_nums[i] > old_nums[i]) {
|
||||||
)
|
return false;
|
||||||
)
|
|
||||||
) {
|
|
||||||
longest = key;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return longest;
|
|
||||||
}
|
}
|
||||||
idx_vals.forEach((val) => {
|
function build_chain(elem) {
|
||||||
let longest = find_longest_chain(val);
|
let best = null;
|
||||||
let mychain = options[longest].slice();
|
for (let chain_end in options) {
|
||||||
mychain.push(val);
|
let chain = options[chain_end];
|
||||||
options[val + 1] = mychain;
|
chain_end = Number.parseInt(chain_end);
|
||||||
});
|
if (elem == null || chain_end < elem[0]) {
|
||||||
let result_chain = find_longest_chain(null);
|
let newchain = chain.slice();
|
||||||
let a = [];
|
if (elem != null) {
|
||||||
for (let i=0; i<cards_content[0].length; i++) {
|
newchain.push(elem);
|
||||||
a.push(true);
|
}
|
||||||
|
if (chain_is_better(best, newchain)) {
|
||||||
|
best = newchain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return best;
|
||||||
}
|
}
|
||||||
options[result_chain].forEach((elem) => {
|
elems.forEach(elem => {
|
||||||
a[elem] = false;
|
let chain = build_chain(elem);
|
||||||
|
options[chain[chain.length - 1][0]] = chain;
|
||||||
});
|
});
|
||||||
return idx_vals.map(idx => a[idx]);
|
let result_chain = build_chain(null);
|
||||||
|
let corrects = result_chain.map(elem => elem[0]);
|
||||||
|
return elems.map(elem => !corrects.includes(elem[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
var app = new Vue({
|
var app = new Vue({
|
||||||
@ -185,6 +190,7 @@ var app = new Vue({
|
|||||||
selected: null,
|
selected: null,
|
||||||
items: shuffle_cards(0),
|
items: shuffle_cards(0),
|
||||||
},
|
},
|
||||||
|
next_insert_num: null,
|
||||||
solution: [],
|
solution: [],
|
||||||
correction_visible: false,
|
correction_visible: false,
|
||||||
},
|
},
|
||||||
@ -274,8 +280,8 @@ var app = new Vue({
|
|||||||
return this.solution.map(elem => false);
|
return this.solution.map(elem => false);
|
||||||
}
|
}
|
||||||
if (this.store.section == 0) {
|
if (this.store.section == 0) {
|
||||||
let idx_vals = this.solution.map(elem => elem.idx[0]);
|
let elems = this.solution.map(elem => [elem.idx[0], elem.insert_num]);
|
||||||
return choose_incorrects(idx_vals);
|
return choose_incorrects(elems);
|
||||||
} else {
|
} else {
|
||||||
return this.solution.map((elem, i) => {
|
return this.solution.map((elem, i) => {
|
||||||
return elem.idx.length > this.store.section
|
return elem.idx.length > this.store.section
|
||||||
@ -316,11 +322,18 @@ var app = new Vue({
|
|||||||
store_card_visible: function(idx) {
|
store_card_visible: function(idx) {
|
||||||
return !this.solution.some(solution => solution.idx[this.store.section] == idx);
|
return !this.solution.some(solution => solution.idx[this.store.section] == idx);
|
||||||
},
|
},
|
||||||
|
calculate_insert_num: function() {
|
||||||
|
if (this.next_insert_num == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return this.next_insert_num++;
|
||||||
|
},
|
||||||
store_select: function(i) {
|
store_select: function(i) {
|
||||||
if (this.solution.length == 0) {
|
if (this.solution.length == 0) {
|
||||||
this.solution.push({
|
this.solution.push({
|
||||||
idx: [i],
|
idx: [i],
|
||||||
got_revealed: false,
|
got_revealed: false,
|
||||||
|
insert_num: this.calculate_insert_num(),
|
||||||
});
|
});
|
||||||
} else if (i == this.store.selected) {
|
} else if (i == this.store.selected) {
|
||||||
this.store.selected = null;
|
this.store.selected = null;
|
||||||
@ -335,6 +348,7 @@ var app = new Vue({
|
|||||||
this.solution.splice(0, 0, {
|
this.solution.splice(0, 0, {
|
||||||
idx: [this.store.selected],
|
idx: [this.store.selected],
|
||||||
got_revealed: false,
|
got_revealed: false,
|
||||||
|
insert_num: this.calculate_insert_num(),
|
||||||
});
|
});
|
||||||
this.store.selected = null;
|
this.store.selected = null;
|
||||||
},
|
},
|
||||||
@ -349,6 +363,7 @@ var app = new Vue({
|
|||||||
this.solution.splice(this.find_solution(elem)+1, 0, {
|
this.solution.splice(this.find_solution(elem)+1, 0, {
|
||||||
idx: [this.store.selected],
|
idx: [this.store.selected],
|
||||||
got_revealed: false,
|
got_revealed: false,
|
||||||
|
insert_num: this.calculate_insert_num(),
|
||||||
});
|
});
|
||||||
this.store.selected = null;
|
this.store.selected = null;
|
||||||
},
|
},
|
||||||
@ -360,6 +375,12 @@ var app = new Vue({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
show_correction: function() {
|
show_correction: function() {
|
||||||
|
if (this.store.section == 0) {
|
||||||
|
this.solution.forEach((elem, i) => {
|
||||||
|
elem.insert_num = -i;
|
||||||
|
});
|
||||||
|
this.next_insert_num = 1;
|
||||||
|
}
|
||||||
this.correction_visible = true;
|
this.correction_visible = true;
|
||||||
},
|
},
|
||||||
open_next_column: function() {
|
open_next_column: function() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user