struct lsh_iterator* lsh_initialize(int len1, int len2, int(*penalty_)(int, int), int bandwidth, int *result) { struct lsh_iterator* ret; assert (!busy); busy = 1; n1 = len1 + 1, n2 = len2 + 1; /* this is ugly comunication between lsh_initialize_mcmp and lsh_initialize * to check if we have mpenalty */ if (bandwidth < 0) { bandwidth *= -1; } else { mpenalty = NULL; mmpenalty = NULL; } penalty = penalty_; K = bandwidth; adjust_bandwidth(); double_K_plus_1 = 2*K + 1; check_allocation(); edit_distance(); output(); if (result != NULL) { *result = dp_read[n2 - n1 + K]; } ret = (struct lsh_iterator*) malloc(sizeof(struct lsh_iterator)); ret->_row = n1 - 1; ret->_col = n2 - n1 + K; return ret; }
void checkSpell(std::string wrong) { std::vector<std::string> temp; splitStr(wrong, &temp); for (int i = 0;i < temp.size();++i) { std::ifstream myIf("CT2 dict.txt"); std::string data; while (!myIf.eof()) { myIf >> data; int distance = edit_distance(temp[i], data); if (distance == 0) { continue; } else if (distance == 1) { temp[i] = temp[i] + " (" + data + ')'; } } } std::string result; for (int i = 0;i < temp.size() - 1;++i) { result = result + temp[i] + ' '; } result = result + temp[temp.size() - 1] + '.'; std::cout << result << '\n'; }
int distcorr(FILE *outfile, long generation) { long i, j, editdist; double treedist; for (i = 0; i < psize; i++) { for (j = 0; j < i; j++) { treedist = phyl_leafdistance(&phyltree, seq[i].name, seq[j].name); if (treedist < 0.0) { fprintf(stderr, "distcorr: error #%f determining tree distance between %s and %s\n", treedist, seq[i].name, seq[j].name); continue; } editdist = edit_distance(seq[i].genome.length, seq[i].genome.g, seq[j].genome.length, seq[j].genome.g); if (editdist < 0) { fprintf(stderr, "distcorr: error #%ld determining edit distance between %s and %s\n", editdist, seq[i].name, seq[j].name); continue; } fprintf(outfile, "%f %ld\n", treedist, editdist); } } for (i = 0; i < psize; i++) free_genome(&(seq[i].genome)); free(seq); phyl_free_tree(&phyltree); return (0); }
int FusionMapper::calcED(string seq, int contig, int start, int end) { // check start and end are in same strand if( (start>=0 && end<=0) || (start<=0 && end>=0) ) { return -1; } string& fusionSeq = mIndexer->mFusionSeq[contig]; // check the overflow if(abs(start)>=fusionSeq.length() || abs(end)>=fusionSeq.length()) return -2; string str = seq; if(start < 0) { Sequence s(seq); Sequence rc = ~s; str = rc.mStr; int tmp = start; start = -end; end = -tmp; } string refstr = fusionSeq.substr(start, end-start+1); return edit_distance(str.c_str(), str.length(), refstr.c_str(), refstr.length()); }
/** * Are the two given strings similar according to some metric? */ int similarity(const char* str1, int len1, const char* str2, int len2) noexcept { // Do not check very short strings, because they create too many false // positives. if (len1 < MIN_STRLEN || len2 < MIN_STRLEN) { return -1; } // Do not check very long strings. This keeps memory use and run time for // Levenshtein algorithm in check. if (len1 >= MAX_STRLEN || len2 >= MAX_STRLEN) { return -1; } // Check if one string is a substring of the other. This will also check // if both strings differ only in case. if (strcasestr(str1, str2) || strcasestr(str2, str1)) { return 0; } // Do not check strings if they have very different lengths, they can't // be similar according to Levenshtein anyway. if (std::abs(len1 - len2) >= MAX_EDIT_DISTANCE) { return -1; } // Check Levenshtein edit distance. const int distance = edit_distance(str1, len1, str2, len2); if (distance <= MAX_EDIT_DISTANCE) { return distance; } return -1; }
void write_dmt(void) { long i, j; short d; fprintf(dmt_file, "%ld\r\n", psize); fprintf(dmt_file, "%ld\r\n", generation); j = 0; for (i = 0; i < world_width; i++) { if (plant[i] != NULL) { tmp_index[j++] = i; } } for (i = 0; i < psize - 1; i++) { for (j = i + 1; j < psize; j++) { d = (short) edit_distance(plant[tmp_index[i]]->genome.length, (char *) plant[tmp_index[i]]->genome.g, plant[tmp_index[j]]->genome.length, (char *) plant[tmp_index[j]]->genome.g); fwrite_int16array(&d, 1, dmt_file); } } fflush(dmt_file); }
/// // Version 1 /// int edit_distance(char *s1, char *s2, uint l1, uint l2) { if (l1 == 0) { return (int) l2 * del(' '); } if (l2 == 0) { return (int) l1 * ins(' '); } #ifdef DEBUG printf("%.*s, %.*s\n", l1, s1, l2, s2); #endif int c1 = edit_distance(s1, s2, l1 - 1, l2) + ins(s1[l1]); int c2 = edit_distance(s1, s2, l1, l2 - 1) + del(s2[l2]); int c3 = edit_distance(s1, s2, l1 - 1, l2 - 1) + match(s1[l1], s2[l2]); int c = min3(c1, c2, c3); #ifdef DEBUG printf("edit_distance(%.*s, %.*s) = %d\n", l1, s1, l2, s2, c); #endif return c; }
int main() { int t; for(scanf("%d",&t);t--;) { scanf("%s",string1); scanf("%s",string2); printf("%d\n",edit_distance(strlen(string1),strlen(string2))); } return 0; }
main(){ //char Y[50] = "ATCGGTATC"; //char X[50] = "ATGAATCGT"; char Y[50] = "TRACEBACK"; char X[50] = "BACKTRACK"; printf("point1"); printf("point2\n"); edit_distance(X,Y,0,9,0,9); printf("done"); }
int main() { char a[MAX_LEN]; char b[MAX_LEN]; scanf("%s", a); scanf("%s", b); int dis = edit_distance(a, strlen(a), b, strlen(b)); printf("Edit Distance: %d\n", dis); return 0; }
int main(int argc, char **argv) { if (argc < 3) { usage(argc, argv); return 0; } char *word1 = argv[1]; char *word2 = argv[2]; //dump(word1, word2, m); int distance = edit_distance(word1, word2); printf("%d\n", distance); return 0; }
vector<char> predict(const string& chain_code,const vector<Train>& trains){ LOGD("predict start"); vector<char> probabilities; probabilities.clear(); int cost = edit_distance(chain_code,trains[0].path); LOGD("predict prob before"); probabilities.push_back(trains[0].label); LOGD("predict prob after"); for(int i = 1; i < (int) trains.size(); i++){ LOGD("%d",i); int cnow = edit_distance(chain_code,trains[i].path); if (cnow < cost){ cost = cnow; probabilities.clear(); probabilities.push_back(trains[i].label); } else if (cnow == cost){ probabilities.push_back(trains[i].label); } } LOGD("predict end"); return probabilities; }
int main(void) { printf("Please enter string 1: "); char *s1 = GetString(); printf("Please enter string 2: "); char *s2 = GetString(); printf("The edit distance is: %d\n", edit_distance(s1, s2)); }
int main(void) { plan_tests(89); test_lcs(); test_lev(); test_rdl(); test_dl(); /* Unsupported edit distance measure */ enum ed_measure badmeasure = (enum ed_measure)-1; ok1(edit_distance("ab", 2, "ba", 2, badmeasure) == (ed_dist)-1); return exit_status(); }
Calculates Levenshtein's edit distance between strings \"a\" and \"b\"\n"); static PyObject * editdist_distance(PyObject *self, PyObject *args) { char *a, *b; int alen, blen, r; if (!PyArg_ParseTuple(args, "s#s#", &a, &alen, &b, &blen)) return NULL; r = edit_distance(a, alen, b, blen); if (r == -1) { PyErr_SetString(PyExc_MemoryError, "Out of memory"); return NULL; } return PyInt_FromLong(r); }
/** * [FuzzyFilter::rank_find rank the result of the FuzzyFilter::find using edit distance] * @param source [str1] * @param targets [target strings] * @param f [function that filter the strings, such as to_lower_case()] * @return [vector of matched strings sorted by edit distance] */ FuzzyFilter::VecRankResult FuzzyFilter::rank_find( const String &source, const VecString &targets, String (*f)(const String &) ) const { VecRankResult results; VecString matches = find(source, targets, f); for(int i=0; i<matches.size(); i++) { int disance = edit_distance(f(source), f(matches[i])); results.push_back(RankResult(matches[i], disance)); } std::sort(results.begin(), results.end()); return results; }
int hardsubx_process_frames_linear(struct lib_hardsubx_ctx *ctx, struct encoder_ctx *enc_ctx) { // Do an exhaustive linear search over the video int got_frame; int dist; int cur_sec,total_sec,progress; int frame_number = 0; int64_t begin_time = 0,end_time = 0,prev_packet_pts = 0; char *subtitle_text=NULL; char *prev_subtitle_text=NULL; while(av_read_frame(ctx->format_ctx, &ctx->packet)>=0) { if(ctx->packet.stream_index == ctx->video_stream_id) { frame_number++; //Decode the video stream packet avcodec_decode_video2(ctx->codec_ctx, ctx->frame, &got_frame, &ctx->packet); if(got_frame && frame_number % 25 == 0) { float diff = (float)convert_pts_to_ms(ctx->packet.pts - prev_packet_pts, ctx->format_ctx->streams[ctx->video_stream_id]->time_base); if(abs(diff) < 1000*ctx->min_sub_duration) //If the minimum duration of a subtitle line is exceeded, process packet continue; // sws_scale is used to convert the pixel format to RGB24 from all other cases sws_scale( ctx->sws_ctx, (uint8_t const * const *)ctx->frame->data, ctx->frame->linesize, 0, ctx->codec_ctx->height, ctx->rgb_frame->data, ctx->rgb_frame->linesize ); // Send the frame to other functions for processing if(ctx->subcolor==HARDSUBX_COLOR_WHITE) { subtitle_text = _process_frame_white_basic(ctx,ctx->rgb_frame,ctx->codec_ctx->width,ctx->codec_ctx->height,frame_number); } else { subtitle_text = _process_frame_color_basic(ctx, ctx->rgb_frame, ctx->codec_ctx->width,ctx->codec_ctx->height,frame_number); } _display_frame(ctx, ctx->rgb_frame,ctx->codec_ctx->width,ctx->codec_ctx->height,frame_number); cur_sec = (int)convert_pts_to_s(ctx->packet.pts, ctx->format_ctx->streams[ctx->video_stream_id]->time_base); total_sec = (int)convert_pts_to_s(ctx->format_ctx->duration, AV_TIME_BASE_Q); progress = (cur_sec*100)/total_sec; activity_progress(progress,cur_sec/60,cur_sec%60); if(subtitle_text==NULL) continue; if(!strlen(subtitle_text)) continue; char *double_enter = strstr(subtitle_text,"\n\n"); if(double_enter!=NULL) *(double_enter)='\0'; //subtitle_text = prune_string(subtitle_text); end_time = convert_pts_to_ms(ctx->packet.pts, ctx->format_ctx->streams[ctx->video_stream_id]->time_base); if(prev_subtitle_text) { //TODO: Encode text with highest confidence dist = edit_distance(subtitle_text, prev_subtitle_text, strlen(subtitle_text), strlen(prev_subtitle_text)); if(dist > (0.2 * fmin(strlen(subtitle_text), strlen(prev_subtitle_text)))) { add_cc_sub_text(ctx->dec_sub, prev_subtitle_text, begin_time, end_time, "", "BURN", CCX_ENC_UTF_8); encode_sub(enc_ctx, ctx->dec_sub); begin_time = end_time + 1; } } // if(ctx->conf_thresh > 0) // { // if(ctx->cur_conf >= ctx->prev_conf) // { // prev_subtitle_text = strdup(subtitle_text); // ctx->prev_conf = ctx->cur_conf; // } // } // else // { // prev_subtitle_text = strdup(subtitle_text); // } prev_subtitle_text = strdup(subtitle_text); prev_packet_pts = ctx->packet.pts; } } av_packet_unref(&ctx->packet); } add_cc_sub_text(ctx->dec_sub, prev_subtitle_text, begin_time, end_time, "", "BURN", CCX_ENC_UTF_8); encode_sub(enc_ctx, ctx->dec_sub); activity_progress(100,cur_sec/60,cur_sec%60); }
bool refine_borders(const char* const p, const size_t len_p, const char* const t, const size_t len_t, const unsigned int max_errs, size_t* out_offset_p, size_t* out_offset_t1, size_t* out_offset_t2, unsigned int* out_edit_distance) { const size_t t_win= MIN(len_p+max_errs, len_t); const unsigned int* Mp= edit_distance(t, t_win, p, len_p); const char* const rt= reverse(t, len_t); const char* const rp= reverse(p, len_p); const unsigned int* Ms= edit_distance(rt, t_win, rp, len_p); unsigned int* const min_pp= NPALLOC(unsigned int, len_p+1); unsigned int* const min_sp= NPALLOC(unsigned int, len_p+1); unsigned int* const min_pos_pp= NPALLOC(unsigned int, len_p+1); unsigned int* const min_pos_sp= NPALLOC(unsigned int, len_p+1); min_pp[0]= 0; min_pos_pp[0]= 0; size_t pos= t_win+1; for (size_t i= 0; i<len_p; ++i) { min_pp[i+1]= Mp[pos]; min_pos_pp[i+1]= 0; for (size_t j= 0; j<t_win; ++j) { ++pos; if (min_pp[i+1]>Mp[pos]) { min_pp[i+1]= Mp[pos]; min_pos_pp[i+1]= j+1; } } ++pos; } min_sp[0]= 0; min_pos_sp[0]= 0; pos= t_win+1; for (size_t i= 0; i<len_p; ++i) { min_sp[i+1]= Ms[pos]; min_pos_sp[i+1]= 0; for (size_t j= 0; j<t_win; ++j) { ++pos; if (min_sp[i+1]>Ms[pos]) { min_sp[i+1]= Ms[pos]; min_pos_sp[i+1]= j+1; } } ++pos; } size_t off_p= 0; size_t off_t1= min_pos_pp[0]; size_t off_t2= min_pos_sp[len_p]; unsigned int min= min_pp[0]+min_sp[len_p]; int best_burset_freq= getBursetFrequency_adaptor(t, off_t1, len_t-off_t2); for (size_t i= 1; i<=len_p; ++i) { const int curr_burset_freq= getBursetFrequency_adaptor(t, min_pos_pp[i], len_t-min_pos_sp[len_p-i]); const unsigned int curr= min_pp[i]+min_sp[len_p-i]; if ((min>curr) || ((min==curr) && (curr_burset_freq>best_burset_freq))) { min= curr; off_p= i; off_t1= min_pos_pp[i]; off_t2= min_pos_sp[len_p-i]; best_burset_freq= curr_burset_freq; } } *out_offset_p= off_p; *out_offset_t1= off_t1; *out_offset_t2= len_t-off_t2; *out_edit_distance= min; pfree(Mp); pfree(rt); pfree(rp); pfree(Ms); pfree(min_pp); pfree(min_pos_pp); pfree(min_sp); pfree(min_pos_sp); return MAX(0, min)<=max_errs; }
void lc3_run_test_case(lc3_test& test, const std::string& filename, int seed) { lc3_state state; // Preliminary stuff if (seed != -1) srand(seed); lc3_init(state, test.randomize, test.randomize); if (test.true_traps) lc3_set_true_traps(state, 1); if (test.interrupt_enabled) state.interrupt_enabled = 1; bool disable_plugins = test.disable_plugins; state.max_stack_size = 0; state.max_call_stack_size = -1; state.in_lc3test = true; try { LC3AssembleOptions options; options.multiple_errors = false; options.warnings_as_errors = false; options.process_debug_comments = false; options.enable_warnings = false; options.disable_plugins = disable_plugins; lc3_assemble(state, filename, options); } catch (LC3AssembleException e) { throw e.what(); } std::stringstream* newinput = new std::stringstream(); // Set up test environment for (unsigned int i = 0; i < test.input.size(); i++) { lc3_test_input& input = test.input[i]; int value_calc; int address_calc = 0; unsigned short effective_address; ///TODO flip the condition here so that if new types are added you don't have to check for it here... if (input.type != TEST_IO && input.type != TEST_REGISTER && input.type != TEST_PC && input.type != TEST_SUBROUTINE && lc3_calculate(state, input.address, address_calc) == -1) throw "An address expression " + input.address + " was not formed correctly."; else if (input.type == TEST_REGISTER) { if (input.address.size() != 2) throw "Register format is RX where x is between 0-7 found: " + input.address; address_calc = input.address[1] - '0'; if (address_calc > 7 || address_calc < 0) throw "Invalid register " + input.address; } else lc3_calculate(state, input.address, address_calc); effective_address = (unsigned short) address_calc; switch (input.type) { case TEST_VALUE: if (lc3_calculate(state, input.value, value_calc)) throw "<in test-value> A value expression " + input.value + " was malformed."; state.mem[effective_address] = (short) value_calc; break; case TEST_REGISTER: if (lc3_calculate(state, input.registerval, value_calc)) throw "<in test-register> A value expression " + input.registerval + " was malformed."; state.regs[effective_address] = (short) value_calc; break; case TEST_PC: if (lc3_calculate(state, input.pcval, value_calc)) throw "<in test-pc> A value expression " + input.pcval + " was malformed."; state.pc = (unsigned short) value_calc; break; case TEST_POINTER: if (lc3_calculate(state, input.pointer, value_calc)) throw "<in test-pointer> An expression was " + input.pointer + " malformed."; state.mem[(unsigned short) state.mem[effective_address]] = (short) value_calc; break; case TEST_STRING: for (unsigned int j = 0; j < input.text.size(); j++) state.mem[state.mem[effective_address] + j] = input.text[j]; state.mem[(unsigned short) (state.mem[effective_address] + input.text.size())] = 0; break; case TEST_ARRAY: for (unsigned int j = 0; j < input.array.size(); j++) { if (lc3_calculate(state, input.array[j], value_calc)) throw "<in test-array> An expression was " + input.array[j] + " malformed."; state.mem[(unsigned short) (state.mem[effective_address] + j)] = (short) value_calc; } break; case TEST_IO: newinput->str(input.io); break; case TEST_SUBROUTINE: break; default: throw "Unknown test type"; } if (input.type == TEST_SUBROUTINE) { lc3_subr_input& subr = input.subroutine; int pc; int r7; int r6; int r5; if (lc3_calculate(state, subr.name, pc) == -1) throw "<in test-subr> invalid subroutine name given " + subr.name; if (lc3_calculate(state, subr.stack, r6) == -1) throw "<in test-subr> stack expression was malformed " + subr.stack; if (lc3_calculate(state, subr.r7, r7) == -1) throw "<in test-subr> r7 expression was malformed " + subr.r7; if (lc3_calculate(state, subr.r5, r5) == -1) throw "<in test-subr> r5 expression was malformed " + subr.r5; state.pc = (unsigned short) pc; state.regs[6] = (unsigned short)(r6 - subr.params.size()); state.regs[7] = (unsigned short) r7; state.regs[5] = (unsigned short) r5; state.mem[state.regs[7]] = 0xF025; for (unsigned int j = 0; j < subr.params.size(); j++) { if (lc3_calculate(state, subr.params[j], value_calc)) throw "<in test-subr> param expression " + subr.params[j] + " was malformed."; state.mem[(unsigned short)state.regs[6] + j] = (short) value_calc; } // This fixes the issue in which a subroutine is being tested, but it makes calls to other subroutines who takes a // different number of parameters than the subroutine under test. // If the file uses subroutine annotations then overwrite it. for (const auto& info : subr.subroutines) { int address = 0; if (lc3_calculate(state, info.name, address) == -1) throw "<in test-subr> invalid subroutine name given " + info.name; lc3_subroutine_info test_info = info; test_info.address = (unsigned short) address; state.subroutines[(unsigned short)address] = test_info; } } } state.input = newinput; // Setup output capture device std::stringstream* newoutput = new std::stringstream(); state.output = newoutput; std::stringstream* newwarning = new std::stringstream(); state.warning = newwarning; if (test.has_max_executions) { unsigned long i = 0; // Do this num times or until halted. while (i < test.max_executions && !state.halted) { //printf("%04x: %s (%x)\n", state.pc, lc3_disassemble(state, state.mem[state.pc]).c_str(), (unsigned short)state.mem[state.pc]); /*printf("R0 %6d|x%04x\tR1 %6d|x%04x\tR2 %6d|x%04x\tR3 %6d|x%04x\nR4 %6d|x%04x\tR5 %6d|x%04x\tR6 %6d|x%04x\tR7 %6d|x%04x\nCC: %s\tPC: %04x\n\n", state.regs[0], (unsigned short)state.regs[0], state.regs[1], (unsigned short)state.regs[1], state.regs[2], (unsigned short)state.regs[2], state.regs[3], (unsigned short)state.regs[3], state.regs[4], (unsigned short)state.regs[4], state.regs[5], (unsigned short)state.regs[5], state.regs[6], (unsigned short)state.regs[6], state.regs[7], (unsigned short)state.regs[7], (state.n ? "N" : (state.z ? "Z" : "P")), (unsigned short) state.pc);*/ // Step one instruction lc3_step(state); // Increment instruction count i++; } //lc3_run(state, test.max_executions); } else lc3_run(state); // Fill in the output values test.has_halted = state.halted; test.executions = state.executions; test.warnings = state.warnings; test.warning = newwarning->str(); bool test_passed = true; unsigned int test_points = 0; unsigned int test_max_points = 0; // Check test environment for (unsigned int i = 0; i < test.output.size(); i++) { std::stringstream expected; std::stringstream actual; lc3_test_output& output = test.output[i]; int value_calc; short short_cmp; int address_calc = 0; unsigned short effective_address; std::string str; std::vector<short> arrayexpected; std::vector<short> arrayactual; if (output.type != TEST_IO && output.type != TEST_REGISTER && output.type != TEST_PC && lc3_calculate(state, output.address, address_calc) == -1) throw "An address expression " + output.address + " was not formed correctly."; else if (output.type == TEST_REGISTER) { address_calc = output.address[1] - '0'; if (address_calc > 7) throw "Invalid register " + output.address; } effective_address = (unsigned short) address_calc; output.passed = true; output.earned = 0; switch (output.type) { case TEST_VALUE: if (lc3_calculate(state, output.value, value_calc)) throw "<in test-value> An expression " + output.value + " was malformed."; short_cmp = (short) value_calc; output.passed = lc3_test_check(output, &state.mem[effective_address], &short_cmp); actual << state.mem[effective_address]; expected << short_cmp; break; case TEST_REGISTER: if (lc3_calculate(state, output.registerval, value_calc)) throw "<in test-register> An expression " + output.registerval + " was malformed."; short_cmp = (short) value_calc; output.passed = lc3_test_check(output, &state.regs[effective_address], &short_cmp); actual << state.regs[effective_address]; expected << short_cmp; break; case TEST_PC: if (lc3_calculate(state, output.pcval, value_calc)) throw "<in test-pc> An expression " + output.pcval + " was malformed."; short_cmp = (short) value_calc; output.passed = lc3_test_check(output, &state.pc, &short_cmp); actual << state.pc; expected << short_cmp; break; case TEST_POINTER: if (lc3_calculate(state, output.pointer, value_calc)) throw "<in test-pointer> An expression " + output.pointer + " was malformed."; short_cmp = (short) value_calc; output.passed = lc3_test_check(output, &state.mem[(unsigned short)state.mem[effective_address]], &short_cmp); actual << state.mem[(unsigned short)state.mem[effective_address]]; expected << short_cmp; break; case TEST_STRING: value_calc = (unsigned short)state.mem[effective_address]; short_cmp = state.mem[(unsigned short)value_calc]; while(short_cmp > 0 && short_cmp <= 255) { actual.put((char) short_cmp); value_calc++; short_cmp = state.mem[(unsigned short)value_calc]; } str = actual.str(); output.passed = lc3_test_check(output, &str, &output.text); expected << output.text; break; case TEST_ARRAY: for (unsigned int j = 0; j < output.array.size(); j++) { if (lc3_calculate(state, output.array[j], value_calc)) throw "<in test-array> An expression " + output.array[j] + " was malformed."; arrayexpected.push_back(state.mem[(unsigned short)(state.mem[effective_address] + j)]); arrayactual.push_back((short)value_calc); actual << state.mem[(unsigned short)(state.mem[effective_address] + j)] << " "; expected << (short)value_calc << " "; } output.passed = lc3_test_check(output, &arrayactual, &arrayexpected); break; case TEST_IO: str = newoutput->str(); output.passed = lc3_test_check(output, &str, &output.io); actual << str; expected << output.io; break; case TEST_SUBROUTINE: break; default: throw "Unknown test type"; } if (output.type != TEST_SUBROUTINE) { if (output.passed) output.earned = output.points; } if (output.type == TEST_SUBROUTINE) { std::stringstream extra; lc3_subr_output& subr = output.subroutine; std::vector<short> expected_stack; std::vector<short> actual_stack; std::vector<short> locals; std::vector<short> params; for (int j = (int)subr.locals.size() - 1; j >= 0; j--) { if (lc3_calculate(state, subr.locals[j], value_calc)) throw "<in test-subr> A local variable expression " + subr.locals[i] + "was malformed."; expected_stack.push_back((short)value_calc); locals.push_back((short) value_calc); } int r7; int r6; int r5; int answer; if (lc3_calculate(state, subr.stack, r6) == -1) throw "<in test-subr> stack expression " + subr.stack + " was malformed"; if (lc3_calculate(state, subr.r7, r7) == -1) throw "<in test-subr> r7 expression " + subr.r7 + " was malformed"; if (lc3_calculate(state, subr.r5, r5) == -1) throw "<in test-subr> r5 expression " + subr.r5 + " was malformed"; if (lc3_calculate(state, subr.answer, answer) == -1) throw "<in test-subr> answer expression " + subr.answer + " was malformed"; expected_stack.push_back((short)r5); expected_stack.push_back((short)r7); expected_stack.push_back((short)answer); for (unsigned int j = 0; j < subr.params.size(); j++) { if (lc3_calculate(state, subr.params[j], value_calc)) throw "<in test-subr> A param expression " + subr.params[j] + " was malformed."; expected_stack.push_back((short)value_calc); params.push_back((short) value_calc); } // Code to get the students stack frame unsigned short actual_r6 = (unsigned short) r6; if (state.first_level_calls.size() >= 1) { const auto& call_info = state.first_level_calls[0]; unsigned short subr_location = call_info.address; if (state.subroutines.find(subr_location) == state.subroutines.end()) { extra << " [WARNING] Could not determine number of parameters for subroutine " << lc3_sym_rev_lookup(state, subr_location) << " at address " << std::hex << "0x" << subr_location << "\n"; } unsigned short start = call_info.r6 + call_info.params.size(); // Screams... if (start >= actual_r6) extra << " [WARNING] Could not get students stack frame.\n" " Is the student managing the stack correctly?\n"; else actual_stack.assign(state.mem + start, state.mem + actual_r6); } else if (state.first_level_calls.empty()) { int num_params = subr.params.size(); // Get at least the parameters student could probably not save anything... actual_stack.assign(state.mem + (actual_r6 - num_params), state.mem + actual_r6); // Get additional addresses modified unsigned short start = actual_r6 - num_params - 1; while (state.memory_ops.find(start) != state.memory_ops.end()) { if (!state.memory_ops[start].writes) break; actual_stack.insert(actual_stack.begin(), state.mem[start]); start--; } } for (unsigned int j = 0; j < expected_stack.size(); j++) expected << std::hex << "0x" << expected_stack[j] << " "; expected << " r5: " << std::hex << "0x" << (short)r5 << " r6: " << std::hex << "0x" << (actual_r6 - subr.params.size() - 1) << " r7: " << std::hex << "0x" << (short)(r7 + 1); for (unsigned int j = 0; j < actual_stack.size(); j++) actual << std::hex << "0x" << actual_stack[j] << " "; actual << " r5: " << std::hex << "0x" << state.regs[5] << " r6: " << std::hex << "0x" << state.regs[6] << " r7: " << std::hex << "0x" << state.regs[7]; // now that I have all information available time for some checks. std::map<short, int> actual_stack_map; for (unsigned int j = 0; j < actual_stack.size(); j++) actual_stack_map[actual_stack[j]] += 1; int points = 0; // If they get something wrong then it will also be wrong in edit distance // so cut some slack if you get a value wrong. int ed_forgiveness = 0; if (actual_stack_map[(short)answer] > 0) { actual_stack_map[(short)answer] -= 1; points += subr.points_answer; extra << CHECK << ANSWER_FOUND << " +" << subr.points_answer << ".\n"; } else { ed_forgiveness++; extra << MISS << ANSWER_FOUND << " -" << subr.points_answer << ".\n"; } if (state.regs[6] == (short)(actual_r6 - subr.params.size() - 1)) { points += subr.points_r6; extra << CHECK << R6_FOUND << " +" << subr.points_r6 << ".\n"; } else { extra << MISS << R6_FOUND << " -" << subr.points_r6 << ".\n"; } if (actual_stack_map[(short)r7] > 0 && state.regs[7] == (short)(r7+1)) { actual_stack_map[(short)r7] -= 1; points += subr.points_r7; extra << CHECK << R7_FOUND << " +" << subr.points_r7 << ".\n"; } else { // Don't count if just r7 was clobbered if (actual_stack_map[(short)r7] <= 0) ed_forgiveness++; extra << MISS << R7_FOUND << " -" << subr.points_r7 << ".\n"; } if (actual_stack_map[(short)r5] > 0 && state.regs[5] == (short)r5) { actual_stack_map[(short)r5] -= 1; points += subr.points_r5; extra << CHECK << R5_FOUND << " +" << subr.points_r5 << ".\n"; } else { if (actual_stack_map[(short)r5] <= 0) ed_forgiveness++; extra << MISS << R5_FOUND << " -" << subr.points_r5 << ".\n"; } for (unsigned int j = 0; j < params.size(); j++) { if (actual_stack_map[params[j]] > 0) { actual_stack_map[params[j]] -= 1; points += subr.points_params; extra << CHECK << params[j] << " " << PARAM_FOUND << " +" << subr.points_params << ".\n"; } else { ed_forgiveness++; extra << MISS << params[j] << " " << PARAM_FOUND << " -" << subr.points_params << ".\n"; } } bool all_locals_wrong = true; for (unsigned int j = 0; j < locals.size(); j++) { if (actual_stack_map[locals[j]] > 0) { actual_stack_map[locals[j]] -= 1; points += subr.points_locals; all_locals_wrong = false; extra << CHECK << locals[j] << " " << LOCAL_FOUND << " +" << subr.points_locals << ".\n"; } else { ed_forgiveness++; extra << MISS << locals[j] << " " << LOCAL_FOUND << " -" << subr.points_locals << ".\n"; } } // Subroutine calls check. std::set<lc3_subroutine_call_info, lc3_subroutine_call_info_cmp> actual_calls(state.first_level_calls.begin(), state.first_level_calls.end()); std::set<lc3_subroutine_call_info, lc3_subroutine_call_info_cmp> expected_calls; for (const auto& expected_call : subr.calls) { lc3_subroutine_call_info info; int addr = lc3_sym_lookup(state, expected_call.name); if (addr == -1) throw "Invalid subroutine name given in <call> " + expected_call.name; for (unsigned int i = 0; i < expected_call.params.size(); i++) { int param; if (lc3_calculate(state, expected_call.params[i], param) == -1) throw "<in test-subr/call> param expression " + expected_call.params[i] + " was malformed"; info.params.push_back(param); } info.address = addr; info.r6 = 0; expected_calls.insert(info); } for (const auto& call : expected_calls) { std::stringstream call_name; call_name << lc3_sym_rev_lookup(state, call.address) << "("; if (state.subroutines.find(call.address) == state.subroutines.end()) call_name << "?"; for (unsigned int i = 0; i < call.params.size(); i++) { call_name << std::hex << "0x" << call.params[i]; if (i != call.params.size() - 1) call_name << ","; } call_name << ")"; if (actual_calls.find(call) != actual_calls.end()) { extra << CHECK << "Call " << call_name.str() << " made correctly.\n"; points += subr.points_calls; } else { extra << MISS << "Call " << call_name.str() << " was not made.\n"; } } for (const auto& call : actual_calls) { std::stringstream call_name; std::string name = lc3_sym_rev_lookup(state, call.address); if (name.empty()) call_name << "0x" << std::hex << call.address << "("; else call_name << name << "("; if (state.subroutines.find(call.address) == state.subroutines.end()) call_name << "?"; for (unsigned int i = 0; i < call.params.size(); i++) { call_name << std::hex << "0x" << call.params[i]; if (i != call.params.size() - 1) call_name << ","; } call_name << ")"; if (expected_calls.find(call) == expected_calls.end()) { extra << MISS << "Unexpected Call " << call_name.str() << " made.\n"; } } // Read answer check sigh... if (subr.points_read_answer > 0) { for (const auto& call : actual_calls) { if (expected_calls.find(call) != expected_calls.end() && !call.params.empty()) { if (state.memory_ops[call.r6 - 1].reads > 0) { extra << CHECK << "Read answer from stack.\n"; points += subr.points_read_answer; } else extra << MISS << "Did not read answer from stack.\n"; } } } // If all local variables are wrong then it can be argued that they was saving registers // And forgot to save locals... if (all_locals_wrong) { // Bro do you even calling convention if (actual_stack.size() > subr.params.size() + 3) // Truncate stack to last num_params + 3 elements the stuff we care about (don't do expected since ed forgiveness handles it). actual_stack.erase(actual_stack.begin(), actual_stack.begin() + (actual_stack.size() - subr.params.size() - 3)); if (!subr.locals.empty()) extra << " All locals were not found, so locals aren't included in structure check.\n"; } else { if (actual_stack.size() > expected_stack.size()) expected_stack.insert(expected_stack.begin(), actual_stack.begin(), actual_stack.begin() + (actual_stack.size() - expected_stack.size())); } int ed_grade = edit_distance(actual_stack, expected_stack); points -= (ed_grade - ed_forgiveness) * subr.deductions_edist; int mistakes = ed_grade - ed_forgiveness; if (mistakes == 0) extra << " Found no structural mistakes in the stack. No changes needed.\n"; else extra << " Found " << mistakes << " structural mistakes in stack -" << subr.deductions_edist * mistakes << ".\n"; output.passed = (ed_grade == 0) && (ed_forgiveness == 0); output.extra_output += extra.str(); output.earned = points; } test_passed = test_passed && output.passed; test_points += output.earned; test_max_points += output.points; output.expected = expected.str(); output.actual = actual.str(); } // Tear down delete state.input; delete state.output; delete state.warning; test.passed = test_passed; test.points = test_points; test.max_points = test_max_points; }
int test() { std::string s1, s2; s1 = "duckduckgo"; s2 = "duckduckgoose"; cerr<<"Edit Distance("<<s1<<", "<<s2<<"): "<<edit_distance(s1, s2)<<endl; assert(edit_distance(s1, s2) == 3); s1 = "duckduckgoose"; s2 = "duckduckgo"; cerr<<"Edit Distance("<<s1<<", "<<s2<<"): "<<edit_distance(s1, s2)<<endl; assert(edit_distance(s1, s2) == 3); s1 = "duckduckgo.com"; s2 = "duckduckgoose"; cerr<<"Edit Distance("<<s1<<", "<<s2<<"): "<<edit_distance(s1, s2)<<endl; assert(edit_distance(s1, s2) == 4); s1 = "duckduckgoose"; s2 = "duckduckgo.com"; cerr<<"Edit Distance("<<s1<<", "<<s2<<"): "<<edit_distance(s1, s2)<<endl; assert(edit_distance(s1, s2) == 4); s1 = "duckduckgo.com"; s2 = "dukgo.com"; cerr<<"Edit Distance("<<s1<<", "<<s2<<"): "<<edit_distance(s1, s2)<<endl; assert(edit_distance(s1, s2) == 5); s1 = "luck"; s2 = "duck"; cerr<<"Edit Distance("<<s1<<", "<<s2<<"): "<<edit_distance(s1, s2)<<endl; assert(edit_distance(s1, s2) == 1); s1 = "deer"; s2 = "duck"; cerr<<"Edit Distance("<<s1<<", "<<s2<<"): "<<edit_distance(s1, s2)<<endl; assert(edit_distance(s1, s2) == 3); s1 = "elephant"; s2 = "duck"; cerr<<"Edit Distance("<<s1<<", "<<s2<<"): "<<edit_distance(s1, s2)<<endl; assert(edit_distance(s1, s2) == 8); s1 = "duck"; s2 = "elephant"; cerr<<"Edit Distance("<<s1<<", "<<s2<<"): "<<edit_distance(s1, s2)<<endl; assert(edit_distance(s1, s2) == 8); s1 = "abracadabra magic! magic! magic!"; s2 = "the great Hoodini"; int x = 0; clock_t start = clock(); const int ntimes = 50000; for (int i = 0; i < ntimes; ++i) { x = edit_distance(s1, s2); } clock_t end = clock(); double sec_diff = (double)(end - start) / CLOCKS_PER_SEC; cerr<<"Edit Distance("<<s1<<", "<<s2<<"): "<<x<<endl; cerr<<"Time to compute "<<ntimes<<" times: "<<sec_diff<<" second. sec/compare: "<<sec_diff/ntimes<<endl; return 0; }
inline size_t EditDistance(const Sequence& s1, const Sequence& s2) { return edit_distance(s1.str(), s2.str()); }