function simplifie (ch) {
// ((2*7)*4)+3 ==> 2*4*7+3
function maxtab (tab) {
// [0,1,2,2,2,1,1,0,0] ==> renvoie 2
let max = -1
for (let k = 0; k < tab.length; k++) {
if (tab[k] > max) max = tab[k]
}
return max
}
function sommetab (tab) {
// [0,1,2,2,2,1,1,0,0] ==> renvoie 2
let s = 0
for (let k = 0; k < tab.length; k++) {
s += tab[k]
}
return s
}
function nbnulstab (tab) {
let nb = 0
for (let k = 0; k < tab.length; k++) {
if (tab[k] == 0) nb++
}
return nb
}
function expression (ch) {
// 3*7 ==> [true,3,7,2]
// 3*6*4 ==> [true,3,4,6,2]
// 2*6+5 ==> [false]
function estdans (liste, ch) {
// estdans(["+","*"],"4+5*4*6"] renvoie [1,2]
const retour = [0, 0, 0, 0]
for (let k = 0; k < ch.length; k++) {
for (let p = 0; p < liste.length; p++) {
if (liste[p] == ch.charAt(k)) {
retour[p]++
}
}
}
return retour
}
function nboperations (ch) {
// 3*7+5==> [2,false] car pas les mêmes
// 2+5+3 ==> [2,true] car les mêmes
const tab = estdans(['+', '-', '*', '/'], ch)
// const max = maxtab(tab)
const som = sommetab(tab)
// si som=max alors il n’y a qu’une seule operation
const nb = 4 - nbnulstab(tab)
if (nb === 1) return [som, true]
return [som, false]
}
let ope = ch.indexOf('+')
if (ope === -1) ope = ch.indexOf('-')
if (ope === -1) ope = ch.indexOf('*')
if (ope === -1) ope = ch.indexOf('/')
ope = ch.charAt(ope)//*
const tab = nboperations(ch)
if (!tab[1]) return [false]
let operande1 = ch.substring(0, ch.indexOf(ope))
let operande2 = ch.substring(1 + ch.indexOf(ope))
let o3
if (Number(operande2) < Number(operande1)) {
o3 = operande2
operande2 = operande1
operande1 = o3
}
return [operande1, operande2, ope]
}
function interieur (ch) {
// ((2*7)*4)+3 ==> [1;5]
let n = 0
const poids = []
for (let k = 0; k < ch.length; k++) {
if (ch.charAt(k) == '(') { n++ }
if (ch.charAt(k) == ')') { n-- }
poids[k] = n
}
const max = maxtab(poids)
const chpoids = poids.join('')
const i1 = chpoids.indexOf(max)
const i2 = chpoids.indexOf((max - 1), i1)
// rangement des termes de la parenthese interieure
const ssch = ch.substring(i1 + 1, i2)
const tab = expression(ssch)//
// le même opérateur
// premier cas ((expression) +
if ((ch.charAt(i1 - 1) == '(') && (ch.charAt(i2 + 1) == '+')) {
ch = ch.substring(0, i1 - 1) + tab[0] + tab[2] + tab[1] + ch.substring(i2) + 1
}
// 2e cas ((expression) *
if ((ch.charAt(i1 - 1) == '(') && (ch.charAt(i2 + 1) == '*')) {
ch = ch.substring(0, i1) + tab[0] + tab[2] + tab[1] + ch.substring(i2 + 1)
}
}
interieur(ch)
return ch
} // simplifie
/**
* À documenter
* @param tirage
* @param compte
* @param ope
* @constructor
*/
function CompteEstBon (tirage, compte, ope) {
if (tirage.length <= 1) {
this.solution = 'impossible'
return
}
if (tirage.length >= 7) {
this.solution = 'impossible2'
return
}
const that = this
this.tirage = tirage
this.noeuds = []
this.compte = compte
this.ceb = false
this.ope = ope // si 4 opérations
// 3 on enlève la division
// 2 on enlève la multiplication est la fdivision
this.choix = [
[], // tirage de longueur 0
[], // tirage de longueur 1, pas moyen d’en prendre 2
[[0, 1]],
[[0, 1], [0, 2], [1, 2]],
[[0, 1], [0, 2], [0, 3], [1, 2], [1, 3], [2, 3]],
[[0, 1], [0, 2], [0, 3], [0, 4], [1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]],
[[0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [1, 2], [1, 3], [1, 4], [1, 5], [2, 3], [2, 4], [2, 5], [3, 4], [3, 5], [4, 5]]
]
this.solutions = []
const objetcomptebon = this
function Noeud (objet) {
// un noeud est un tirage
// objet = {tirage,numero,numpere,numenfants,i1,i2,op}
this.letirage = objet.letirage
this.numero = objet.numero
this.numeropere = objet.numeropere
this.numenfants = objet.numenfants
this.i1 = objet.i1
this.i2 = objet.i2
this.op = objet.op
this.ceb = false
for (let k = 0; k < objet.letirage.length; k++) {
if (objet.letirage[k] == objetcomptebon.compte) {
this.ceb = true
if (k == 0) objetcomptebon.solutions.push(objet.numero)
}
}
if (this.numero == 1) {
for (let k = 0; k < objet.letirage.length; k++) {
if (objet.letirage[k] == objetcomptebon.compte) {
this.ceb = true
objetcomptebon.solutions.push(this.numero)
}
}
}
}
solvecompte(-1, tirage)
// this.noeuds[1] = new Noeud({letirage:tirage,numero:1,numeropere:0,numenfants:[],i1:-1,i2:-1,op:""});
function solvecompte (numeropere, tirage) {
if ((that.tirage.length == 6) && (that.ceb == true)) {
return
}
// objet = {tirage,i1,i2,y,op,numpere}
if (numeropere == -1) {
// sommet du graphe : le tirage passé en paramètre au constructeur CompteEstBon
objetcomptebon.noeuds[1] = new Noeud({
letirage: tirage,
numero: 1,
numeropere: 0,
numenfants: [],
i1: -1,
i2: -1,
op: ''
})
solvecompte(1, tirage)
} else {
for (let k = 0; k < objetcomptebon.choix[tirage.length].length; k++) {
const couple = objetcomptebon.choix[tirage.length][k]
let max
if (that.ope == 3) max = 2
if (that.ope == 4) max = 4
if (that.ope == 2) max = 1
for (let ope = 0; ope <= max; ope++) {
if (!((ope == 2) && (tirage[couple[0]] == 1 || tirage[couple[1]] == 1))) {
const ob = objetcomptebon.operation(ope, tirage[couple[0]], tirage[couple[1]])
if (ob.valide) {
const autretirage = objetcomptebon.nouveautirage(tirage, couple[0], couple[1], ob.res)
const num = objetcomptebon.noeuds.length
objetcomptebon.noeuds.push(new Noeud({
letirage: autretirage,
numero: num,
numeropere,
numenfants: [],
i1: couple[0],
i2: couple[1],
op: ope
}))
if (objetcomptebon.noeuds[objetcomptebon.noeuds.length - 1].ceb) {
that.ceb = true
}
objetcomptebon.noeuds[numeropere].numenfants.push(num)
solvecompte(num, autretirage)
}
}
}
}
}
}
}
// effectue l’operation x ope y et renvoie o.res
// si le résultat n’est pas valide alors l’objet renvoyé contient o.valide = false;
CompteEstBon.prototype.operation = function (ope, x, y) {
function divise (x, y) {
// 5,2 = 2,5 donc renvoie FALSE
const toto = x / y
if (Math.abs(Math.round(toto) - toto) < 0.0000001) return true
return false
}
const objetretour = { valide: true, res: 0 }
switch (ope) {
case 0:
objetretour.res = x + y
break
case 1:
if (x - y <= 0) objetretour.valide = false
else objetretour.res = x - y
break
case 2:
objetretour.res = x * y
break
case 3:
if (divise(x, y) == false) objetretour.valide = false
else objetretour.res = Math.round(x / y)
break
case 4:
if (divise(y, x) == false) objetretour.valide = false
else objetretour.res = Math.round(y / x)
break
}
return objetretour
}
// remplace les éléments i1 et i2 du tableau tirage par y
CompteEstBon.prototype.nouveautirage = function (tab, i1, i2, y) {
const nouveautirage = []
nouveautirage.push(y)
for (let k = 0; k < tab.length; k++) {
if ((k != i1) && (k != i2)) nouveautirage.push(tab[k])
}
return nouveautirage
}
CompteEstBon.prototype.debug = function debug () {
/// /objet = {tirage,numero,numpere,numenfants,i1,i2,op}
let ch = ''
for (let k = 1; k < this.noeuds.length; k++) {
ch += 'noeud ' + k + '\n'
ch += '[' + this.noeuds[k].letirage + '] numero:' + this.noeuds[k].numero + ' pere:' + this.noeuds[k].numeropere + ' enf:' +
this.noeuds[k].numenfants + ' param:(' + this.noeuds[k].i1 + ' ' + this.noeuds[k].i2 + ' ' + this.noeuds[k].op + ') ceb=' + this.noeuds[k].ceb
ch += '\n'
}
return ch
}
CompteEstBon.prototype.affichenoeud = function (k) {
return '[' + this.noeuds[k].letirage + '] numero:' + this.noeuds[k].numero + ' pere:' + this.noeuds[k].numeropere + ' enf:' +
this.noeuds[k].numenfants + ' param:(' + this.noeuds[k].i1 + ' ' + this.noeuds[k].i2 + ' ' + this.noeuds[k].op + ') ceb=' + this.noeuds[k].ceb
}
CompteEstBon.prototype.affichesolutions = function (bool) {
const objet = this
let tabascendants = []
function retourneexpression (ope, a, b) {
switch (ope) {
case 0:
return a + '+' + b
case 1:
return a + '-' + b
case 2:
return a + '*' + b
case 3:
return a + '/' + b
case 4:
return b + '/' + a
}
}
function ascendants (n) {
tabascendants.push(n)
if (objet.noeuds[n].numeropere != 0) {
ascendants(objet.noeuds[n].numeropere)
}
}
function nouveautab (tab, i1, i2, ope) {
const ntab = []
ntab.push('(' + retourneexpression(ope, tab[i1], tab[i2]) + ')')
for (let k = 0; k < tab.length; k++) {
if ((k != i1) && (k != i2)) ntab.push(tab[k])
}
return ntab
}
let result = ''
if (this.solution === 'impossible') return 'Au moins 2 opérandes'
if (this.solution === 'impossible2') return 'Pas plus de 3 opérandes'
if (!this.solutions.length) {
let min = 1000
let numeromeilleur = 0
for (let k = 1; k < this.noeuds.length; k++) {
if (Math.abs(this.noeuds[k].letirage[0] - this.compte) < min) {
numeromeilleur = k
min = Math.abs(this.noeuds[k].letirage[0] - this.compte)
}
}
ascendants(numeromeilleur)
let tab = objet.noeuds[tabascendants[tabascendants.length - 1]].letirage
result = 'Pas de solution.<br> La plus proche est:<br>'
for (let k = tabascendants.length - 2; k >= 0; k--) {
const Enfant = objet.noeuds[tabascendants[k]]
tab = nouveautab(tab, Enfant.i1, Enfant.i2, Enfant.op)
}
result += this.noeuds[numeromeilleur].letirage[0] + ' = ' + simplifie(tab[0].substring(1, tab[0].length - 1)) + '\n'
return result
}
tabascendants = []
if (bool) {
result = ''
for (let j = 0; j < this.solutions.length; j++) {
tabascendants = []
ascendants(this.solutions[j])
let tab = objet.noeuds[tabascendants[tabascendants.length - 1]].letirage
for (let k = tabascendants.length - 2; k >= 0; k--) {
const Enfant = objet.noeuds[tabascendants[k]]
tab = nouveautab(tab, Enfant.i1, Enfant.i2, Enfant.op)
}
result += this.compte + ' = ' + simplifie(tab[0].substring(1, tab[0].length - 1)) + '<br>'
}
return result
}
// bool est false
ascendants(this.solutions[0])
result = 'Le compte est bon : <br>'
let tab = objet.noeuds[tabascendants[tabascendants.length - 1]].letirage
for (let k = tabascendants.length - 2; k >= 0; k--) {
const Enfant = objet.noeuds[tabascendants[k]]
tab = nouveautab(tab, Enfant.i1, Enfant.i2, Enfant.op)
}
result += this.compte + ' = ' + simplifie(tab[0].substring(1, tab[0].length - 1)) + '\n'
return result
}
export default CompteEstBon