From 61f1e168f1def99227c326da5b10688cfa850986 Mon Sep 17 00:00:00 2001 From: bharatm29 Date: Sat, 30 Mar 2024 17:59:31 +0530 Subject: [PATCH] add pydiff: A simple file diff python script --- OTHERS/PyDiff/README.md | 15 +++++ OTHERS/PyDiff/file1.txt | 14 +++++ OTHERS/PyDiff/file2.txt | 14 +++++ OTHERS/PyDiff/pydiff.py | 118 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 161 insertions(+) create mode 100644 OTHERS/PyDiff/README.md create mode 100644 OTHERS/PyDiff/file1.txt create mode 100644 OTHERS/PyDiff/file2.txt create mode 100644 OTHERS/PyDiff/pydiff.py diff --git a/OTHERS/PyDiff/README.md b/OTHERS/PyDiff/README.md new file mode 100644 index 00000000..d3fdcef5 --- /dev/null +++ b/OTHERS/PyDiff/README.md @@ -0,0 +1,15 @@ +## PyDiff +A simple python script to compare two files using *Dynamic Programming* based algorithm. + +Usage: +```sh +py pydiff.py file1.txt file2.txt +``` + +Output: +```sh +file1.txt | - 13 | mattis justo quis porta porttitor. +file2.txt | + 13 | Aenean mattis justo quis porta porttitor. +file1.txt | - 10 | Nullam elementum nunc in massa fringilla, sit amet iaculis elit blandit. +file2.txt | + 10 | elementum nunc in massa fringilla, sit amet iaculis elit blandit. +``` diff --git a/OTHERS/PyDiff/file1.txt b/OTHERS/PyDiff/file1.txt new file mode 100644 index 00000000..0fa5f2bf --- /dev/null +++ b/OTHERS/PyDiff/file1.txt @@ -0,0 +1,14 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. +Nulla volutpat mauris in magna posuere, in volutpat turpis pulvinar. +Mauris semper ante non maximus vulputate. +Fusce sollicitudin justo ut arcu blandit, id feugiat ex rhoncus. +Suspendisse lacinia nisl sit amet vestibulum varius. +Sed vestibulum erat in urna tempus mollis. +Aliquam varius lectus eget dui consequat, sed aliquet diam ultricies. +Sed a lectus a orci blandit accumsan. +Etiam eu augue ac ipsum tempus lobortis at vitae nibh. +Nullam elementum nunc in massa fringilla, sit amet iaculis elit blandit. +Nam et nulla fermentum ligula laoreet malesuada sed nec risus. +Pellentesque maximus velit non massa faucibus, vel aliquam ante pharetra. +mattis justo quis porta porttitor. +Donec dignissim ligula et pretium feugiat. diff --git a/OTHERS/PyDiff/file2.txt b/OTHERS/PyDiff/file2.txt new file mode 100644 index 00000000..b348e2d1 --- /dev/null +++ b/OTHERS/PyDiff/file2.txt @@ -0,0 +1,14 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. +Nulla volutpat mauris in magna posuere, in volutpat turpis pulvinar. +Mauris semper ante non maximus vulputate. +Fusce sollicitudin justo ut arcu blandit, id feugiat ex rhoncus. +Suspendisse lacinia nisl sit amet vestibulum varius. +Sed vestibulum erat in urna tempus mollis. +Aliquam varius lectus eget dui consequat, sed aliquet diam ultricies. +Sed a lectus a orci blandit accumsan. +Etiam eu augue ac ipsum tempus lobortis at vitae nibh. +elementum nunc in massa fringilla, sit amet iaculis elit blandit. +Nam et nulla fermentum ligula laoreet malesuada sed nec risus. +Pellentesque maximus velit non massa faucibus, vel aliquam ante pharetra. +Aenean mattis justo quis porta porttitor. +Donec dignissim ligula et pretium feugiat. diff --git a/OTHERS/PyDiff/pydiff.py b/OTHERS/PyDiff/pydiff.py new file mode 100644 index 00000000..df581bdc --- /dev/null +++ b/OTHERS/PyDiff/pydiff.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 + +import argparse + + +class Colors: + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKCYAN = '\033[96m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + + +ADD = "Add" +REMOVE = "Remove" +IGNORE = "Ignore" + +def print_matrix(m1, m2): + for i in range(len(m1) + 1): + for j in range(len(m2) + 1): + print(f"{m1[i][j]}({m2[i][j]})", end=", ") + print() + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("file1") + parser.add_argument("file2") + args = parser.parse_args() + + file1 = args.file1 + file2 = args.file2 + + with open(file1, 'r') as f: + file_content1 = f.read() + + with open(file2, 'r') as f: + file_content2 = f.read() + + lines1 = file_content1.splitlines() + lines2 = file_content2.splitlines() + + n = len(lines1) + m = len(lines2) + + distances = [[0 for _ in range(m + 1)] for _ in range(n + 1)] + action = [['0' for _ in range(m + 1)] for _ in range(n + 1)] + + distances[0][0] = 0 + action[0][0] = IGNORE + + for j in range(1, m + 1): + i = 0 + distances[i][j] = j + action[i][j] = ADD + + for i in range(1, n + 1): + j = 0 + distances[i][j] = i + action[i][j] = REMOVE + + for i in range(1, n + 1): + for j in range(1, m + 1): + if lines1[i - 1] == lines2[j - 1]: + action[i][j] = IGNORE + distances[i][j] = distances[i - 1][j - 1] + continue + + removeOps = distances[i - 1][j] + addOps = distances[i][j - 1] + + distances[i][j] = removeOps + action[i][j] = REMOVE + + if distances[i][j] > addOps: + distances[i][j] = addOps + action[i][j] = ADD + + distances[i][j] += 1 + + i = n + j = m + res = [] + + while i > 0 and j > 0: + _action = action[i][j] + if _action == IGNORE: + i -= 1 + j -= 1 + elif _action == ADD: + j -= 1 + res.append((file2, ADD, j + 1, lines2[j])) + elif _action == REMOVE: + i -= 1 + res.append((file1, REMOVE, i + 1, lines1[i])) + else: + raise Exception("Unhandled action") + + if not res: + print(f"{Colors.HEADER}They are the same :){Colors.ENDC}") + exit(0) + + for (fname, ac, lineno, line) in res: + if ac == ADD: + print(fr"{Colors.HEADER}{fname}{Colors.ENDC} | { + Colors.OKGREEN}+ {lineno} | {line}{Colors.ENDC}") + + elif ac == REMOVE: + print(fr"{Colors.HEADER}{fname}{Colors.ENDC} | { + Colors.FAIL}- {lineno} | {line}{Colors.ENDC}") + + +if __name__ == "__main__": + main()