/*
 *  Public Domain
 *  C++ & QT Implementation Of Levenshtein Distance
 *
 *  Additions for QT by Muhammad Mominul Huque <mominul2082@gmail.com>
 *
 *  From:
 *  1. https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C.2B.2B
 */
#ifndef Q_LEVENSHTEIN_HPP
#define Q_LEVENSHTEIN_HPP

#include <QString>
#include <algorithm>

int levenshtein_distance(const QString &s1, const QString &s2) {
  // To change the type this function manipulates and returns, change
  // the return type and the types of the two variables below.
  int s1len = s1.size();
  int s2len = s2.size();

  auto column_start = (decltype(s1len)) 1;

  auto column = new decltype(s1len)[s1len + 1];
  std::iota(column + column_start, column + s1len + 1, column_start);

  for (auto x = column_start; x <= s2len; x++) {
    column[0] = x;
    auto last_diagonal = x - column_start;
    for (auto y = column_start; y <= s1len; y++) {
      auto old_diagonal = column[y];
      auto possibilities = {
          column[y] + 1,
          column[y - 1] + 1,
          last_diagonal + (s1[y - 1] == s2[x - 1] ? 0 : 1)
      };
      column[y] = std::min(possibilities);
      last_diagonal = old_diagonal;
    }
  }
  auto result = column[s1len];
  delete[] column;
  return result;
}

#endif /* end of include guard: Q_LEVENSHTEIN_HPP */
