public static Tuple <int, IEnumerable <String> > gradeGrammarEquality(ContextFreeGrammar solution, ContextFreeGrammar attempt, int maxGrade, long timelimit) { List <String> feedback = new List <String>(); Tuple <long, List <String>, List <String> > res = GrammarUtilities.findDifferenceWithTimelimit(solution, attempt, true, timelimit); long correct = res.Item1; List <String> missing = res.Item2; List <String> tooMuch = res.Item3; long allChecked = correct + missing.Count + tooMuch.Count; if (missing.Count == 0 && tooMuch.Count == 0) //correct { feedback.Add(String.Format("All tests passed! (checked {0} words)", correct)); return(Tuple.Create(maxGrade, (IEnumerable <String>)feedback)); } //wrong int grade = (int)Math.Floor(correct * maxGrade / (double)allChecked); double percMissing = missing.Count * 100 / (double)allChecked; double percTooMuch = tooMuch.Count * 100 / (double)allChecked; if (missing.Count > 0) { feedback.Add(String.Format("Your solution misses words (~{0:F2}% of checked words). One of them is \"{1}\".", percMissing, missing[0])); } if (tooMuch.Count > 0) { feedback.Add(String.Format("Your solution accepts too many words (~{0:F2}% of checked words). One of them is \"{1}\".", percTooMuch, tooMuch[0])); } return(Tuple.Create(grade, (IEnumerable <String>)feedback)); }
public static Tuple <int, IEnumerable <String> > gradeCYK(ContextFreeGrammar grammar, String word, HashSet <Nonterminal>[][] attempt, int maxGrade, int feedbackLevel) { List <String> feedback = new List <String>(); int n = word.Length; int checked_length = 0; var sol = GrammarUtilities.cyk(grammar, word); bool all_correct_sofar = true; for (int len = 1; len <= n; len++) { for (int start = 0; start + len <= n; start++) { HashSet <Nonterminal> must = sol[len - 1][start].Item1; HashSet <Nonterminal> was = attempt[len - 1][start]; Nonterminal missingExample = null; Production missingApplicableProduction = null; int missing = 0; Nonterminal tooMuchExample = null; int tooMuch = 0; //check if all must are present foreach (Nonterminal nt in must) { if (!was.Contains(nt)) { missing++; all_correct_sofar = false; //save as example and look for corresponding applicable production for hint if (missingApplicableProduction != null) { continue; //not needed: already found example } missingExample = nt; foreach (var applicable in sol[len - 1][start].Item2) { if (applicable.Item1.Lhs.Equals(nt)) { missingApplicableProduction = applicable.Item1; break; } } } } //check if all given are correct foreach (Nonterminal nt in was) { if (!must.Contains(nt)) { tooMuchExample = nt; tooMuch++; all_correct_sofar = false; } } //feedback String fieldName = String.Format("({0},{1})", start + 1, start + len); if (feedbackLevel >= 2) { if (missing != 0) { feedback.Add(String.Format("You are missing some nonterminals in field {0} e.g. {1}", fieldName, missingExample)); } if (tooMuch != 0) { feedback.Add(String.Format("There are nonterminals in field {0} that don't belong there... e.g. {1}", fieldName, tooMuchExample)); } } else if (feedbackLevel >= 1) { if (missing != 0) { feedback.Add(String.Format("You are missing some nonterminals in field {0}... (hint: The production \"{1}\" is applicable.)", fieldName, missingApplicableProduction)); } if (tooMuch != 0) { feedback.Add(String.Format("There are nonterminals in field {0} that don't belong there...", fieldName)); } } else { if (missing != 0) { feedback.Add(String.Format("You are missing some nonterminals in field {0}...", fieldName)); } if (tooMuch != 0) { feedback.Add(String.Format("There are nonterminals in field {0} that don't belong there...", fieldName)); } } } if (!all_correct_sofar) { break; } checked_length = len; } //grade int grade = (int)Math.Floor(checked_length * maxGrade / (double)n); //all correct? if (feedback.Count == 0) { feedback.Add("Correct!"); } return(Tuple.Create(grade, (IEnumerable <String>)feedback)); }
public static Tuple <int, IEnumerable <String> > gradeWordsInGrammar(ContextFreeGrammar grammar, IEnumerable <String> wordsIn, IEnumerable <String> wordsOut, int maxGrade) { int cases = 0; double correct = 0; var terminals = new List <char>(); foreach (GrammarSymbol s in grammar.GetNonVariableSymbols()) { terminals.Add(s.ToString()[0]); } List <String> feedback = new List <String>(); HashSet <String> done = new HashSet <String>(); //for duplicate checking foreach (String w in wordsIn) { cases++; //handle duplicates if (done.Contains(w)) { feedback.Add(String.Format("The word \"{0}\" was used more than once!", w)); continue; } else { done.Add(w); } int prefixLength = GrammarUtilities.longestPrefixLength(grammar, w); if (prefixLength < 0) { correct++; //correct } else //wrong { feedback.Add(String.Format("The word \"{0}\" isn't in the language of the grammar! (hint: the word '{1}' is still possible prefix)", w, w.Substring(0, prefixLength))); } } foreach (String w in wordsOut) { cases++; //handle duplicates if (done.Contains(w)) { feedback.Add(String.Format("The word \"{0}\" was used more than once!", w)); continue; } else { done.Add(w); } if (!GrammarUtilities.isWordInGrammar(grammar, w)) //correct { //only useful terminals? bool allUsefull = true; char problem = 'a'; foreach (char c in w) { if (!terminals.Contains(c)) { allUsefull = false; problem = c; break; } } if (allUsefull) { correct += 1; //full points } else //only half the points { correct += 0.5; feedback.Add(String.Format("The word \"{0}\" uses the symbol '{1}' that is not part of the alphabet...", w, problem)); } } else //wrong { feedback.Add(String.Format("The word \"{0}\" is in the language of the grammar!", w)); } } int grade = (int)Math.Floor(correct * maxGrade / (double)cases); //all correct? if (grade == maxGrade) { feedback.Add("Correct!"); } return(Tuple.Create(grade, (IEnumerable <String>)feedback)); }