package tools;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.util.Vector;

import com.wcohen.ss.Jaccard;
import com.wcohen.ss.JaroWinkler;
import com.wcohen.ss.Levenstein;
import com.wcohen.ss.SoftTFIDF;

public class CompareUtilities {
	/*
	 * public static final String DEFAULT_DISTANCE_REFERENCE =
	 * "DEFAULT_DISTANCE_REFERENCE" ; public static final String
	 * EDIT_DISTANCE_REFERENCE = "EDIT_DISTANCE_REFERENCE" ; public static final
	 * String JACCARD_DISTANCE_REFERENCE = "JACCARD_DISTANCE_REFERENCE" ; public
	 * static final String JARO_DISTANCE_REFERENCE = "JARO_DISTANCE_REFERENCE" ;
	 * public static final String TFIDF_DISTANCE_REFERENCE =
	 * "TFIDF_DISTANCE_REFERENCE" ; public static final String
	 * COSINE_DISTANCE_REFERENCE = "COSINE_DISTANCE_REFERENCE" ; public static
	 * final String YEAR_DISTANCE_REFERENCE = "YEAR_DISTANCE_REFERENCE" ;
	 */
	
	
	public static final int DEFAULT_DISTANCE_REFERENCE = 1 << 0;
	public static final int EDIT_DISTANCE_REFERENCE = 1 << 1;
	public static final int JACCARD_DISTANCE_REFERENCE = 1 << 2;
	public static final int JARO_DISTANCE_REFERENCE = 1 << 3;
	public static final int TFIDF_DISTANCE_REFERENCE = 1 << 4;
	public static final int COSINE_DISTANCE_REFERENCE = 1 << 5;
	public static final int YEAR_DISTANCE_REFERENCE = 1 << 6;

	public static final int TITLE_DISTANCE_REFERENCE = 1 << 20;

	private static final int MAX_LENGTH_EDIT_DISTANCE = 1000;
	private static final int COST_DELETION = 1;
	private static final int COST_INSERTION = 1;
	private static final int COST_SUBSTITUTION = 1;

	private static int[][] d = new int[2][MAX_LENGTH_EDIT_DISTANCE];

	private static Levenstein levenstein = new Levenstein();
	private static Jaccard jaccard = new Jaccard();
	private static JaroWinkler jarowinkler = new JaroWinkler();
	private static SoftTFIDF softtfidf = new SoftTFIDF(jarowinkler);

	private static int [] va = new int [20] ;
	private static int [] vb = new int [20] ;
	
	public static double DefaultDistance(String a, String b) {
		return 0;
	}

	public static double EditDistance(String a, String b) {
		if (a.length() >= MAX_LENGTH_EDIT_DISTANCE
				|| b.length() >= MAX_LENGTH_EDIT_DISTANCE) {
			return DefaultDistance(a, b);
		}

		int cur = 0, next = cur ^ 1;
		for (int ib = 0; ib <= b.length(); ib++) {
			d[cur][ib] = ib;
		}
		for (int ia = 1; ia <= a.length(); ia++) {
			d[next][0] = ia;
			for (int ib = 1; ib <= b.length(); ib++) {
				d[next][ib] = Math.min(d[cur][ib] + COST_DELETION,
						d[next][ib - 1] + COST_INSERTION);
				if (a.charAt(ia) == b.charAt(ib)) {
					d[next][ib] = Math.min(d[next][ib], d[cur][ib - 1]);
				} else {
					d[next][ib] = Math.min(d[next][ib], d[cur][ib - 1]
							+ COST_SUBSTITUTION);
				}
			}
			cur = next;
			next ^= 1;
		}
		return (double) d[cur][b.length()] / Math.max(a.length(), b.length());
	}

	public static double JaccardDistance(String a, String b) {

		return 0;
	}

	public static double JaroDistance(String a, String b) {
		return 0;
	}

	public static double TFIDFDistance(String a, String b) {
		return 0;
	}

	public static double CosineDistance(String a, String b) {
		return 0;
	}

	public static double YearDistance(String a, String b) {
		StringTokenizer ta = new StringTokenizer(a, "/-.");
		StringTokenizer tb = new StringTokenizer(b, "/-.");

		Vector<String> va = new Vector<String>(1);
		Vector<String> vb = new Vector<String>(1);
		while (ta.hasMoreTokens()) {
			va.add(ta.nextToken());
		}
		while (tb.hasMoreTokens()) {
			vb.add(tb.nextToken());
		}
		double sim = 0.0, nsim, score;
		String ya, yb;
		int vya, vyb, dif;
		for (int i = 0; i < va.size(); i++) {
			try {
				ya = va.get(i);
				vya = Integer.parseInt(ya);

				for (int j = 0; j < vb.size(); j++) {
					try {
						yb = vb.get(j);
						vyb = Integer.parseInt(yb);
						score = levenstein.score(ya, yb);
						if (score == 0) {
							return 1.0;
						}
						if (score == -1) {
							dif = Math.abs(vya - vyb);
							while (dif > 9)
								dif /= 10;
							nsim = Math.exp(-5.0 * dif / 10);
							if (score > -2 || Math.abs(vya - vyb) < 3) {
								if (sim < 1e5 || sim < nsim) {
									sim = nsim;
								}

							}
						}
						if (score < -1)
							return 0.0;
					} catch (NumberFormatException e) {

					}
				}
			} catch (NumberFormatException e) {

			}
		}
		return sim;
	}

	private static boolean contains(int functionReference, int function) {
		return (functionReference & function) != 0;
	}

	private static int roman2int(String p_roman) {
		int value = 0;
		int[] p_sum_series = new int[p_roman.length()];

		for (int i = 0; i < p_roman.length(); i++) {
			// we need to consider order, XI is 6 whilst IX is 4
			if (p_roman.charAt(i) == 'I')
				p_sum_series[i] = 1;
			else if (p_roman.charAt(i) == 'V')
				p_sum_series[i] = 5;
			else if (p_roman.charAt(i) == 'X')
				p_sum_series[i] = 10;
			else {
				// if we get to here, we don't have a roman numeral, tell user
				// return -1
				//System.out.println("Not Roman Numerial");
				return -1;
			}
		}

		// Now we must deal with the series we have created in the form of
		// an array named p_sum_series
		// eg. III - 1, 1, 1
		// eg. IV - 1, 5
		int counter = 0;
		int next;

		do {
			if (counter == p_sum_series.length - 1)
				next = 0;
			else
				next = p_sum_series[counter + 1];

			if (p_sum_series[counter] >= next)
				value += p_sum_series[counter];
			else
				value = next - p_sum_series[counter]
						- p_sum_series[counter + 1];

			counter++;
		} while (counter < p_sum_series.length);

		return value;
	}

	private static int getValue(String s) {
		int val = -1 ;
		if (s.length() == 0) return -1 ;
		try {
			val = Integer.parseInt(s) ; 
		}
		catch (NumberFormatException e) {
			val = roman2int(s) ;
		}		
		return val ;
	}

	public static double distance(int functionReference, String a, String b) {
		// System.out.println("Comparing: " + functionReference + " -> " + a +
		// ", " + b) ;
		a = a.toLowerCase() ;
		b = b.toLowerCase() ;
		double dis = DefaultDistance(a, b);
		if (contains(functionReference, EDIT_DISTANCE_REFERENCE)) {
			dis = 1.0 - levenstein.score(a, b) * (-1.0)
					/ Math.max(a.length(), b.length());
		}
		if (contains(functionReference, JACCARD_DISTANCE_REFERENCE)) {
			dis = jaccard.score(a, b);
		}
		if (contains(functionReference, JARO_DISTANCE_REFERENCE)) {
			dis = jarowinkler.score(a, b);
		}
		if (contains(functionReference, TFIDF_DISTANCE_REFERENCE)) {
			dis = softtfidf.score(a, b);
		}
		if (contains(functionReference, COSINE_DISTANCE_REFERENCE)) {
			dis = CosineDistance(a, b);
		}
		if (contains(functionReference, YEAR_DISTANCE_REFERENCE)) {
			dis = YearDistance(a, b);
		}
		if (dis > 0.8 && contains(functionReference, TITLE_DISTANCE_REFERENCE)) {
			//if (a.contains("Der _Augenzeuge")) {
				//System.out.println("entered") ;
			//}
			StringTokenizer ta = new StringTokenizer(a, " .:/,-'[]`\"~\\()");
			StringTokenizer tb = new StringTokenizer(b, " .:/,-'[]`\"~\\()");
			int ia = 0, ib = 0 ;
			while (ta.hasMoreTokens()) {
				va [ia] = getValue(ta.nextToken()) ;
				if (va [ia] != -1) {
					ia ++ ;
				}
			}
			while (tb.hasMoreTokens()) {
				vb [ib] = getValue(tb.nextToken()) ;
				if (vb [ib] != -1) {
					ib ++ ;
				}
			}
			
			int cumDif = 0 ;
			for (int i = 0 ; i < ia ; i ++) {
				int best = 1000000 ;
				for (int j = Math.max(0, i - 3) ; j < Math.min(ib, i + 4) ; j ++) {
					best = Math.min(best, Math.abs(va [i] - vb [j])) ;
				}
				if (best < 200) cumDif += best ;
			}
			if (cumDif > 0 && cumDif < 200) {
				return 0.5 ;
			}
			else {
				return dis ;
			}
		}
		return dis;
	}
	
	public static void main(String [] args) {
		BufferedReader inp = new BufferedReader(new InputStreamReader(System.in)) ;
		while (true) {
		String a;
		try {
			a = inp.readLine();
			String b = inp.readLine() ;
			System.out.println("edit distance: " + (1.0 - levenstein.score(a, b) * (-1.0)
					/ Math.max(a.length(), b.length()))) ;
			System.out.println("jaccard: " + jaccard.score(a, b)) ;
			System.out.println("jaro: " + jarowinkler.score(a, b)) ;
			System.out.println("tfidf: " + softtfidf.score(a, b)) ;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		
		
		}
	}
}
