public SolveData Copy() { SolveData res = new SolveData(); res.mapping = this.mapping.Copy(); res.numSolvedWords = this.numSolvedWords; res.solvedWords = new bool[this.solvedWords.Length]; this.solvedWords.CopyTo(res.solvedWords, 0); res.firstcand = new int[this.firstcand.Length]; this.firstcand.CopyTo(res.firstcand, 0); return(res); }
private bool ReduceCandidates(Mapping set, bool[] solvedWords, SolveData data) { Mapping helper = new Mapping(this.calpha.GetAlphabetQuantity()); int rounds = 0; bool dirty = true; while (dirty && rounds < DictionaryAttacker.maxReduceIterations) { dirty = false; for (int wordnum = 0; wordnum < words.Count; wordnum++) { Word w = words[wordnum]; if (solvedWords[wordnum] || !w.Enabled) { continue; } helper.SetEmpty(); for (int c = data.firstcand[wordnum]; c < w.Candidates.Length; c++) { Candidate candidate = w.Candidates[c]; if (set.IsMappingOK(w.ByteValue, candidate.ByteValue)) { helper.EnableMapping(w.ByteValue, candidate.ByteValue); } else { Candidate tmp = w.Candidates[data.firstcand[wordnum]]; w.Candidates[data.firstcand[wordnum]] = candidate; w.Candidates[c] = tmp; data.firstcand[wordnum]++; dirty = true; } } set.IntersectWith(helper); } long mappedTo = 0; for (int i = 0; i < this.calpha.GetAlphabetQuantity(); i++) { if (!set.HasMapping((byte)i)) { return(true); } int mi = set.GetMapping((byte)i); if (mi >= 0) { if ((mappedTo & (1 << mi)) > 0) { return(true); } mappedTo |= (1 << mi); } } rounds++; } return(false); }
private int DetermineNextSubstituationRandomly(bool[] solvedWords, Mapping map, out int index, SolveData data) { int action = -1; int i = 0; while (i < solvedWords.Length * 10) { int cur_index = this.random.Next(solvedWords.Length); if (!(solvedWords[cur_index] || !this.words[cur_index].Enabled)) { index = cur_index; return(1); } i++; } index = 0; return(action); }
private int DetermineNextSubstitutionDeterministic(bool[] solvedWords, Mapping map, out int index, SolveData data) { int score = Int32.MaxValue; int word = -1; for (int i = 0; i < solvedWords.Length; i++) { Word w = this.words[i]; if (solvedWords[i] || !w.Enabled) { continue; } int cur_score = (w.Candidates.Length - data.firstcand[i]); if (cur_score == 0) { index = 0; return(-2); } if (cur_score < score) { score = cur_score; word = i; } } if (score > this.calpha.GetAlphabetQuantity()) { for (int i = 0; i < this.historder.Length; i++) { if (map.IsUniquelyMapped(this.historder[i])) { continue; } byte letter = this.historder[i]; if (this.histogram[letter] == 0) { continue; } index = letter; return(2); } } index = word; if (index == -1) { return(-2); } return(1); }
private void Solve() { //First Mapping Mapping startMap = new Mapping(this.calpha.GetAlphabetQuantity()); startMap.SetFull(); // Prepare solution base data SolveData basis = new SolveData(); basis.solvedWords = new bool[this.words.Count]; basis.numSolvedWords = 0; basis.mapping = startMap; basis.firstcand = new int[this.words.Count]; for (int i = 0; i < this.words.Count; i++) { basis.firstcand[i] = 0; } Stack <SolveData> stack = new Stack <SolveData>(); stack.Push(basis); // Reduce root node if (pruneRootNode) { bool inconsistent = ReduceCandidates(basis.mapping, basis.solvedWords, basis); if (inconsistent) { basis.mapping = startMap.Copy(); } } int rounds = 0; int action; int index; do { if (StopFlag) { break; } rounds++; //// Store new data object to stack SolveData data = stack.Peek().Copy(); //// Break if all words are solved if (data.numSolvedWords == words.Count) { AddKeyToResult(data.mapping, true); break; } // Define next action action = this.DetermineNextSubstitution(data.solvedWords, data.mapping, out index, data); if (action == -1) { AddKeyToResult(data.mapping, true); break; } else if (action == -2) { AddKeyToResult(data.mapping, false); break; } else if (action == 1) { //// Implement action - Word Word w = words[index]; data.solvedWords[index] = true; data.numSolvedWords++; if (!w.Enabled) { continue; } Mapping helper = data.mapping.Copy(); bool leaf = true; if (scrambleWordOrder) { for (int c = data.firstcand[index]; c < w.Candidates.Length; c++) { int d = this.random.Next(w.Candidates.Length - data.firstcand[index]) + data.firstcand[index]; Candidate cc = w.Candidates[c]; Candidate cd = w.Candidates[d]; w.Candidates[d] = cc; w.Candidates[c] = cd; } } for (int c = data.firstcand[index]; c < w.Candidates.Length; c++) { Candidate candidate = w.Candidates[c]; if (!helper.IsMappingOK(w.ByteValue, candidate.ByteValue)) { continue; } leaf = false; helper.SetMapping(w.ByteValue, candidate.ByteValue); bool inconsistent = false; if (pruneEachNode) { inconsistent = ReduceCandidates(helper, data.solvedWords, data); } if (!inconsistent) { data.mapping = helper; data.firstcand[index] = c; stack.Push(data); leaf = false; break; } helper.SetTo(data.mapping); } if (leaf) { AddKeyToResult(helper, false); stack.Pop(); } } else if (action == 2) { /// Implement action - letter byte[] a = new byte[1]; byte[] b = new byte[1]; a[0] = (byte)(index); Mapping helper = data.mapping.Copy(); bool leaf = true; for (int c = 0; c < this.calpha.GetAlphabetQuantity(); c++) { b[0] = (byte)c; if (helper.IsMappingOK(a, b)) { helper.SetMapping(a, b); bool inconsistent = ReduceCandidates(helper, data.solvedWords, data); if (!inconsistent) { data.mapping = helper; leaf = false; break; } helper.SetTo(data.mapping); } } if (leaf) { AddKeyToResult(data.mapping, false); stack.Pop(); } } } while (rounds < DictionaryAttacker.maxIterations); }