From 8ba506bb1b96b20d3baecc9a075823f97061a86e Mon Sep 17 00:00:00 2001 From: afroz23 Date: Sat, 7 Mar 2020 13:45:16 +0530 Subject: [PATCH 01/56] Large_Number_Factorial added --- .../Large_Number_Factorial.c | 53 ++++++++++++++++++ .../Large_Number_Factorial.cpp | 54 +++++++++++++++++++ .../Large_Number_Factorial.java | 37 +++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 Large_Number_Factorial/Large_Number_Factorial.c create mode 100644 Large_Number_Factorial/Large_Number_Factorial.cpp create mode 100644 Large_Number_Factorial/Large_Number_Factorial.java diff --git a/Large_Number_Factorial/Large_Number_Factorial.c b/Large_Number_Factorial/Large_Number_Factorial.c new file mode 100644 index 0000000000..edfc016ecf --- /dev/null +++ b/Large_Number_Factorial/Large_Number_Factorial.c @@ -0,0 +1,53 @@ + +#include +#define max 1000 +int res[max]; +int rs,x,i; +void mult(int x) +{ int i,c = 0; + for (i=0; i=0; i--) + { + printf("%d",res[i]); + } +} + +int main() +{ int n; + printf("Enter a number: "); + scanf("%d",&n); + printf("Factorial is "); + fact(n); +} + +/* +Input : + +Enter a number: 40 + +Output: + +Factorial is 815915283247897734345611269596115894272000000000 + +*/ diff --git a/Large_Number_Factorial/Large_Number_Factorial.cpp b/Large_Number_Factorial/Large_Number_Factorial.cpp new file mode 100644 index 0000000000..72bde7ab7f --- /dev/null +++ b/Large_Number_Factorial/Large_Number_Factorial.cpp @@ -0,0 +1,54 @@ + +#include +using namespace std; +#define max 1000 +int res[max]; +int rs,x,i; +void mult(int x) +{ int i,c = 0; + for (i=0; i=0; i--) + { + cout<>n; + cout<<"Factorial is "; + fact(n); +} + +/* +Input : + +Enter a number: 40 + +Output: + +Factorial is 815915283247897734345611269596115894272000000000 + +*/ diff --git a/Large_Number_Factorial/Large_Number_Factorial.java b/Large_Number_Factorial/Large_Number_Factorial.java new file mode 100644 index 0000000000..2df1288376 --- /dev/null +++ b/Large_Number_Factorial/Large_Number_Factorial.java @@ -0,0 +1,37 @@ +// Calculating Lanrge Number factorial in Java Language + +/* +Here i am using BigInteger class to store the big value of factorial. +*/ + +import java.math.BigInteger; +import java.util.Scanner; +public class fact{ + public static void main(String[] args) { +// Dynamic input using Scanner + Scanner x = new Scanner(System.in); + System.out.print("Enter Number: "); + int n=x.nextInt(); +// Initialise BigInteger -> fact with 1 + BigInteger fact = new BigInteger("1"); +// multiplying every i with fact and store in fact upto n + for(int i=2;i<=n;i++) + { + fact = fact.multiply(new BigInteger(i + "")); + } +// print the fatorial value + System.out.println("Factorial is " + fact); + } +} + + +/* +Input : + +Enter Number: 25 + +Output: + +Factorial is 15511210043330985984000000 + +*/ \ No newline at end of file From 270177092bfb4bc6d470040badd06bcf15bb0f07 Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Mon, 9 Mar 2020 17:48:08 +0530 Subject: [PATCH 02/56] Deleted Java File --- .../Large_Number_Factorial.java | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 Large_Number_Factorial/Large_Number_Factorial.java diff --git a/Large_Number_Factorial/Large_Number_Factorial.java b/Large_Number_Factorial/Large_Number_Factorial.java deleted file mode 100644 index 2df1288376..0000000000 --- a/Large_Number_Factorial/Large_Number_Factorial.java +++ /dev/null @@ -1,37 +0,0 @@ -// Calculating Lanrge Number factorial in Java Language - -/* -Here i am using BigInteger class to store the big value of factorial. -*/ - -import java.math.BigInteger; -import java.util.Scanner; -public class fact{ - public static void main(String[] args) { -// Dynamic input using Scanner - Scanner x = new Scanner(System.in); - System.out.print("Enter Number: "); - int n=x.nextInt(); -// Initialise BigInteger -> fact with 1 - BigInteger fact = new BigInteger("1"); -// multiplying every i with fact and store in fact upto n - for(int i=2;i<=n;i++) - { - fact = fact.multiply(new BigInteger(i + "")); - } -// print the fatorial value - System.out.println("Factorial is " + fact); - } -} - - -/* -Input : - -Enter Number: 25 - -Output: - -Factorial is 15511210043330985984000000 - -*/ \ No newline at end of file From b42f887d3af86caa9dbcab42bf7ed7d05e6c4e5b Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Mon, 9 Mar 2020 17:50:39 +0530 Subject: [PATCH 03/56] Updated Large_Number_Factorial.c Indentation --- Large_Number_Factorial/Large_Number_Factorial.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Large_Number_Factorial/Large_Number_Factorial.c b/Large_Number_Factorial/Large_Number_Factorial.c index edfc016ecf..aaa424c95b 100644 --- a/Large_Number_Factorial/Large_Number_Factorial.c +++ b/Large_Number_Factorial/Large_Number_Factorial.c @@ -4,10 +4,10 @@ int res[max]; int rs,x,i; void mult(int x) -{ int i,c = 0; - for (i=0; i Date: Mon, 9 Mar 2020 17:55:17 +0530 Subject: [PATCH 04/56] Updated Function name --- .../Large_Number_Factorial.c | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/Large_Number_Factorial/Large_Number_Factorial.c b/Large_Number_Factorial/Large_Number_Factorial.c index aaa424c95b..5c71b92157 100644 --- a/Large_Number_Factorial/Large_Number_Factorial.c +++ b/Large_Number_Factorial/Large_Number_Factorial.c @@ -3,10 +3,10 @@ #define max 1000 int res[max]; int rs,x,i; -void mult(int x) +void multiply(int x) { - int i,c = 0; - for (i=0; i=0; i--) - { - printf("%d",res[i]); - } + multiply(x); + } + for (i=rs-1; i>=0; i--){ + printf("%d",res[i]); + } } -int main() -{ int n; - printf("Enter a number: "); - scanf("%d",&n); - printf("Factorial is "); - fact(n); +int main(){ + int n; + printf("Enter a number: "); + scanf("%d",&n); + printf("Factorial is "); + factorial(n); } /* From 62b1a3c80d120907d0a4089a2ffea8409b3b79e4 Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Mon, 9 Mar 2020 18:00:40 +0530 Subject: [PATCH 05/56] Updated c file --- Large_Number_Factorial/Large_Number_Factorial.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Large_Number_Factorial/Large_Number_Factorial.c b/Large_Number_Factorial/Large_Number_Factorial.c index 5c71b92157..659ca83531 100644 --- a/Large_Number_Factorial/Large_Number_Factorial.c +++ b/Large_Number_Factorial/Large_Number_Factorial.c @@ -9,10 +9,9 @@ void multiply(int x) for(i=0; i Date: Mon, 9 Mar 2020 18:05:53 +0530 Subject: [PATCH 06/56] All changes Done in cpp file --- .../Large_Number_Factorial.cpp | 45 +++++++++---------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/Large_Number_Factorial/Large_Number_Factorial.cpp b/Large_Number_Factorial/Large_Number_Factorial.cpp index 72bde7ab7f..f21d5765ec 100644 --- a/Large_Number_Factorial/Large_Number_Factorial.cpp +++ b/Large_Number_Factorial/Large_Number_Factorial.cpp @@ -4,42 +4,39 @@ using namespace std; #define max 1000 int res[max]; int rs,x,i; -void mult(int x) -{ int i,c = 0; - for (i=0; i=0; i--) - { - cout<=0; i--){ + cout<>n; - cout<<"Factorial is "; - fact(n); +{ + int n; + cout<<"Enter a number: "; + cin>>n; + cout<<"Factorial is "; + factorial(n); } /* From f14c921fb4d8a1644cd94bf05059e15dc11d8831 Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Sun, 29 Mar 2020 23:07:00 +0530 Subject: [PATCH 07/56] Tree_Preorder_Traversal.js added --- .../Tree_Preorder_Traversal.js.js | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js new file mode 100644 index 0000000000..8390327e2b --- /dev/null +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js @@ -0,0 +1,83 @@ +//Tree_Preorder_Traversal in javascript +class Node +{ + constructor(data) + { + this.data = data; + this.left = null; //left child of the node + this.right = null; //right child of the node + } +} + +class BinarySearchTree +{ + constructor() + { + this.root = null; + } +//data inserting in tree + insert(data) + { + let node = new Node(data); + if(this.root == null) + { + this.root = node; + }else + { + this.insertNode(this.root, node); + } + } + + insertNode(root, newNode) + { + if(newNode.data < root.data) + { + if(root.left == null) + { + root.left = newNode; + }else + { + this.insertNode(root.left, newNode); + } + }else if(newNode.data > root.data) + { + if(root.right == null) + { + root.right = newNode; + }else + { + this.insertNode(root.right, newNode); + } + } + } + + getRootNode() + { + return this.root; + } + //function of preorder traversal + preorder(root) + { + if(root != null) + { + console.log(root.data); // first line - P L R + this.preorder(root.left); // second line + this.preorder(root.right); // third line + } + } +} +var bst = new BinarySearchTree(); +//tree data insertion statically +bst.insert(3); +bst.insert(5); +bst.insert(1); +bst.insert(6); +bst.insert(4); +var root = bst.getRootNode(); +console.log('Preorder Traversal:'); +bst.preorder(root); +console.log('\n'); + +/* +output: +*/ \ No newline at end of file From c472dc49b52aa6b90a3a7f69325015d9b89a09ea Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Sun, 29 Mar 2020 23:15:55 +0530 Subject: [PATCH 08/56] indentation --- .../Tree_Preorder_Traversal.js.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js index 8390327e2b..0ddcd3f694 100644 --- a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js @@ -22,7 +22,8 @@ class BinarySearchTree if(this.root == null) { this.root = node; - }else + } + else { this.insertNode(this.root, node); } @@ -35,16 +36,19 @@ class BinarySearchTree if(root.left == null) { root.left = newNode; - }else + } + else { this.insertNode(root.left, newNode); } - }else if(newNode.data > root.data) + } + else if(newNode.data > root.data) { if(root.right == null) { root.right = newNode; - }else + } + else { this.insertNode(root.right, newNode); } @@ -80,4 +84,10 @@ console.log('\n'); /* output: +Preorder Traversal: +3 +1 +5 +4 +6 */ \ No newline at end of file From e179bd3f7ec80ffde7c8a6db5339a7661b8336ae Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Tue, 7 Apr 2020 12:18:33 +0530 Subject: [PATCH 09/56] 4 space indentation added --- .../Tree_Preorder_Traversal.js.js | 94 +++++++++---------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js index 0ddcd3f694..ba5f14e833 100644 --- a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js @@ -1,75 +1,74 @@ + //Tree_Preorder_Traversal in javascript class Node { - constructor(data) - { - this.data = data; - this.left = null; //left child of the node - this.right = null; //right child of the node - } + constructor(data) + { + this.data = data; + this.left = null; //left child of the node + this.right = null; //right child of the node + } } - class BinarySearchTree { - constructor() - { - this.root = null; - } + constructor() + { + this.root = null; + } //data inserting in tree - insert(data) - { +insert(data) +{ let node = new Node(data); if(this.root == null) { - this.root = node; + this.root = node; } else { this.insertNode(this.root, node); } - } - - insertNode(root, newNode) - { +} +insertNode(root, newNode) +{ if(newNode.data < root.data) { - if(root.left == null) - { - root.left = newNode; - } - else - { - this.insertNode(root.left, newNode); - } + if(root.left == null) + { + root.left = newNode; + } + else + { + this.insertNode(root.left, newNode); + } } else if(newNode.data > root.data) { - if(root.right == null) - { - root.right = newNode; - } - else - { - this.insertNode(root.right, newNode); - } + if(root.right == null) + { + root.right = newNode; + } + else + { + this.insertNode(root.right, newNode); + } } - } - - getRootNode() - { +} +getRootNode() +{ return this.root; - } - //function of preorder traversal - preorder(root) - { +} +//function of preorder traversal +preorder(root) +{ if(root != null) { - console.log(root.data); // first line - P L R - this.preorder(root.left); // second line - this.preorder(root.right); // third line + console.log(root.data); // first line - P L R + this.preorder(root.left); // second line + this.preorder(root.right); // third line } - } } +} + var bst = new BinarySearchTree(); //tree data insertion statically bst.insert(3); @@ -90,4 +89,5 @@ Preorder Traversal: 5 4 6 -*/ \ No newline at end of file + +*/ From 830184f5dc509ce566d545917126ceab3d4186fe Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Fri, 10 Apr 2020 21:15:35 +0530 Subject: [PATCH 10/56] 4 space indentation and blank line added --- .../Tree_Preorder_Traversal.js.js | 75 ++++++++++--------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js index ba5f14e833..37f9eeb18a 100644 --- a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js @@ -9,6 +9,7 @@ class Node this.right = null; //right child of the node } } + class BinarySearchTree { constructor() @@ -16,58 +17,62 @@ class BinarySearchTree this.root = null; } //data inserting in tree -insert(data) -{ - let node = new Node(data); - if(this.root == null) - { - this.root = node; - } - else - { - this.insertNode(this.root, node); - } -} -insertNode(root, newNode) -{ - if(newNode.data < root.data) + + insert(data) { - if(root.left == null) + let node = new Node(data); + if(this.root == null) { - root.left = newNode; + this.root = node; } else { - this.insertNode(root.left, newNode); + this.insertNode(this.root, node); } } - else if(newNode.data > root.data) + + insertNode(root, newNode) { - if(root.right == null) + if(newNode.data < root.data) { - root.right = newNode; + if(root.left == null) + { + root.left = newNode; + } + else + { + this.insertNode(root.left, newNode); + } } - else + else if(newNode.data > root.data) { - this.insertNode(root.right, newNode); + if(root.right == null) + { + root.right = newNode; + } + else + { + this.insertNode(root.right, newNode); + } } } -} -getRootNode() -{ - return this.root; -} + + getRootNode() + { + return this.root; + } //function of preorder traversal -preorder(root) -{ - if(root != null) + + preorder(root) { - console.log(root.data); // first line - P L R - this.preorder(root.left); // second line - this.preorder(root.right); // third line + if(root != null) + { + console.log(root.data); // first line - P L R + this.preorder(root.left); // second line + this.preorder(root.right); // third line + } } } -} var bst = new BinarySearchTree(); //tree data insertion statically From d1686605f7f2a3094dcb0e1d42a58a38b075c97f Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Mon, 13 Apr 2020 13:46:38 +0530 Subject: [PATCH 11/56] 4 space indentation added in comment. --- Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js index 37f9eeb18a..f891bee41e 100644 --- a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js @@ -16,7 +16,7 @@ class BinarySearchTree { this.root = null; } -//data inserting in tree + //data inserting in tree insert(data) { @@ -61,7 +61,7 @@ class BinarySearchTree { return this.root; } -//function of preorder traversal + //function of preorder traversal preorder(root) { From 39a8e11234cd8d35e4e91d7d9094b39aa101c36b Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Tue, 14 Apr 2020 23:20:15 +0530 Subject: [PATCH 12/56] checking' --- Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js index f891bee41e..c7770bd61c 100644 --- a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js @@ -1,5 +1,5 @@ -//Tree_Preorder_Traversal in javascript + //Tree_Preorder_Traversal in javascript class Node { constructor(data) From b6c85f44e8cf93507865c61ca3a5b1b16a657c7d Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Tue, 14 Apr 2020 23:25:00 +0530 Subject: [PATCH 13/56] Final Commit --- Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js index c7770bd61c..f891bee41e 100644 --- a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js @@ -1,5 +1,5 @@ - //Tree_Preorder_Traversal in javascript +//Tree_Preorder_Traversal in javascript class Node { constructor(data) From a4c623f112f3d4d9ae86064ac40cac5d2867404f Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Sat, 25 Apr 2020 12:18:48 +0530 Subject: [PATCH 14/56] commit 3 --- Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js index f891bee41e..2842a2d6cf 100644 --- a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js @@ -62,7 +62,7 @@ class BinarySearchTree return this.root; } //function of preorder traversal - + preorder(root) { if(root != null) @@ -95,4 +95,4 @@ Preorder Traversal: 4 6 -*/ +*/ \ No newline at end of file From 48249ad65f055e8cb55049d46c750f4944f10830 Mon Sep 17 00:00:00 2001 From: VIJAY07102 <44638395+VIJAY07102@users.noreply.github.com> Date: Mon, 30 Mar 2020 19:45:04 +0530 Subject: [PATCH 15/56] Priority_Queue.py Priority_Queue --- Priority_Queue/Priority_Queue.py | 65 ++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 Priority_Queue/Priority_Queue.py diff --git a/Priority_Queue/Priority_Queue.py b/Priority_Queue/Priority_Queue.py new file mode 100644 index 0000000000..eff1b80fdd --- /dev/null +++ b/Priority_Queue/Priority_Queue.py @@ -0,0 +1,65 @@ +queue = [] + +def insert(data): # To insert values into the Queue + queue.append(data) + +def delete(): # TO remove value from the Priority Queue + try: # Here highest value will be deleted first + max = 0 + for i in range(len(queue)): + if queue[i] > queue[max]: + max = i + + item = queue[max] + del queue[max] + + return item + + except IndexError: # Instead of giving error for empty queue + print("Queue is empty!!") # Displays that 'Queue is empty' + +while 1: + + print("\t1. Insert value in queue\n\t2. Delete value in queue\n\t3. Print Queue\n\t4. Exit") + + opt = int(input("Enter your option:")) + + if opt == 1: + value = int(input("Enter the value:")) + insert(value) + + elif opt == 2: + del_value = delete() + print("\n" + str(del_value) + " is deleted") + + elif opt == 3: + print(queue) + + elif opt == 4: + break + + else: + print("\tInvalid option!\n\tTry Again!!") + +# The program is made of user choice +''' +Example: + 1. Insert value in queue + 2. Delete value in queue + 3. Print Queue + 4. Exit +Enter your option: 1 # Here you have to give value to be inserted in the queue +Enter the value: 12 + 1. Insert value in queue + 2. Delete value in queue + 3. Print Queue + 4. Exit +Enter your option:2 # To delete the value of highest priority(here highest value) +14 is deleted +Enter your option:3 # display the queue +[12, 1, 7] +Enter your option:4 #to exit +If you enter any other value other than (1,2,3,4), You will be shown: + Invalid option! + Try Again!! +''' From bad4dc1f761aa6fe542561210e2a1b021339fe2d Mon Sep 17 00:00:00 2001 From: "Abhushan A. Joshi" <49617450+abhu-A-J@users.noreply.github.com> Date: Wed, 1 Apr 2020 00:26:18 +0530 Subject: [PATCH 16/56] Added implementation of Z-Algorithm in JS (#2607) --- Z_Algorithm/Z_Algorithm.js | 102 +++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 Z_Algorithm/Z_Algorithm.js diff --git a/Z_Algorithm/Z_Algorithm.js b/Z_Algorithm/Z_Algorithm.js new file mode 100644 index 0000000000..351dca2a51 --- /dev/null +++ b/Z_Algorithm/Z_Algorithm.js @@ -0,0 +1,102 @@ +/* +Z algorithm is a linear time string matching algorithm which runs in complexity. +It is used to find all occurrence of a pattern in a string , which is common +string searching problem. +*/ + +const setZArray = combined => { + + // Initiate zArray and fill it with zeros. + const zArray = Array.from({ length: combined.length }, () => 0); + + // Z box boundaries. + let leftIndex = 0, rightIndex = 0, shift = 0; + + // Go through all characters of the zString. + for (let i = 1; i < combined.length; i += 1) { + + if (i > rightIndex) { + + leftIndex = i; + rightIndex = i; + + while ( + rightIndex < combined.length + && combined[rightIndex - leftIndex] === combined[rightIndex] + ) { + + // Expanding Z box right boundary. + rightIndex += 1; + } + + + zArray[i] = rightIndex - leftIndex; + rightIndex -= 1; + + } + + else { + + // Calculate corresponding Z box shift. + shift = i - leftIndex; + + // Check if the value that has been already calculated before + if (zArray[shift] < (rightIndex - i) + 1) { + + zArray[i] = zArray[shift]; + } + else { + + // shift left boundary of Z box to current position. + leftIndex = i; + + // And start comparing characters one by one as we normally do for the case + while ( + rightIndex < combined.length + && combined[rightIndex - leftIndex] === combined[rightIndex] + ) { + rightIndex += 1; + } + + zArray[i] = rightIndex - leftIndex; + + rightIndex -= 1; + } + } + } + + // Return generated zArray. + return zArray; +} + + +zAlgorithm = (text, word) => { + + const wordPositions = []; + + // Concatenate word and text. Word will be a prefix to a text. + const zString = `${word}$${text}`; + + // Generate Z-array for concatenated string. + const zArray = setZArray(zString); + + for (let i = 1; i < zArray.length; i += 1) { + if (zArray[i] === word.length) { + + const wordPosition = i - word.length - 1; + wordPositions.push(wordPosition); + } + } + + // Return the list of word positions. + return wordPositions; +} + + +// I/O and O/P Examples: + +// The postions are: [0,10,16] +console.log(zAlgorithm("omgawesomeomgsftomg", "omg")); + +// The positions are: [3,12] +console.log(zAlgorithm("ohelloworldello", "llo")); From 412de13a3760036301c711283f730ffce163d452 Mon Sep 17 00:00:00 2001 From: HIMANSHU SHARMA Date: Wed, 1 Apr 2020 22:04:44 +0530 Subject: [PATCH 17/56] Created Pancake Sort in C# (#2309) * Create Pancake_Sort.cs * Update Pancake_Sort.cs * Update Pancake_Sort.cs * Update Pancake_Sort.cs * Update Pancake_Sort.cs * Update Pancake_Sort.cs * Update Pancake_Sort.cs * Update Pancake_Sort.cs * Update Pancake_Sort.cs * Update Pancake_Sort.cs * Update Pancake_Sort.cs * Update Pancake_Sort.cs --- Pancake_Sort/Pancake_Sort.cs | 78 ++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 Pancake_Sort/Pancake_Sort.cs diff --git a/Pancake_Sort/Pancake_Sort.cs b/Pancake_Sort/Pancake_Sort.cs new file mode 100644 index 0000000000..14fcf92128 --- /dev/null +++ b/Pancake_Sort/Pancake_Sort.cs @@ -0,0 +1,78 @@ +using System; + +class pancakeSortProgram { + // function swapping adjacent integer in array till from index 0 toindex i + static void flip(int []arr, int i) + { + int temp, start = 0; + while (start < i) + { + temp = arr[start]; + arr[start] = arr[i]; + arr[i] = temp; + start++; + i--; + } + } + // function returning index of max value till index curr_size + static int findMax(int []arr, int n) + { + int mi, i; + for (mi = 0, i = 0; i < n; ++i) + if (arr[i] > arr[mi]) + mi = i; + return mi; + } + + static int pancakeSort(int []arr, int n) + { + for (int curr_size = n; curr_size > 1; --curr_size) + { + // function calling for finding index of max integer + // till the index curr_size + int mi = findMax(arr, curr_size); + // call function flip for swapping if index of max integer + // till the index curr_size is not equal to curr_size-1 + if (mi != curr_size - 1) + { + flip(arr, mi); + flip(arr, curr_size - 1); + } + } + return 0; + } + // function for printing sorted array + static void printArray(int []arr, int arr_size) + { + for (int i = 0; i < arr_size; i++) + Console.Write(arr[i] + " "); + Console.Write(""); + } + + public static void Main (string [] args) + { + int n = Convert.ToInt32(Console.ReadLine());//input size of array + int []arr = new int[n];//initializing array of size n + + for(int i = 0; i < n; i++) + arr[i] = Convert.ToInt32(Console.ReadLine());//input value in array + + pancakeSort(arr, n);// call function which is sorting the input array + Console.Write("Sorted Array: "); + printArray(arr, n);// call fubction which print the sorted array + } +} +/* +Input: +6 +23 +10 +20 +11 +12 +6 +7 + +Output: +Sorted Array: 6 7 10 11 12 20 23 +*/ From 8a48be50725d0bef2be46a74e5f567165bc4e81c Mon Sep 17 00:00:00 2001 From: PrachieNaik <42534757+PrachieNaik@users.noreply.github.com> Date: Wed, 1 Apr 2020 22:27:45 +0530 Subject: [PATCH 18/56] Create Tree_Preorder_Traversal.kt (#2585) * Create Tree_Preorder_Traversal.kt * Update Tree_Preorder_Traversal.kt Taking dynamic input --- .../Tree_Preorder_Traversal.kt | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Tree_Preorder_Traversal/Tree_Preorder_Traversal.kt diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.kt b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.kt new file mode 100644 index 0000000000..18bef0bd6c --- /dev/null +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.kt @@ -0,0 +1,50 @@ +import java.util.* +class Node( + var key:Int, + var left:Node? = null, + var right:Node? = null +) +{ + fun preorderTraversal() + { + print("$key ") + left?.preorderTraversal() + right?.preorderTraversal() + } +} + +fun main() { + var read = Scanner(System.`in`) + println("Enter the size of Array:") + val arrSize = read.nextLine().toInt() + var arr = IntArray(arrSize) + val nodes = mutableListOf>() + println("Enter the array respresentaion of binary tree") + for(i in 0 until arrSize) + { + arr[i] = read.nextLine().toInt() + nodes.add(Node(arr[i])) + } + for(i in 0..arrSize-2) + { + if((i*2)+1 Date: Wed, 1 Apr 2020 22:52:02 +0530 Subject: [PATCH 19/56] add kosaraju algorithm in cpp (#2672) * add kosaraju algorithm in cpp * Update kosaraju_algorithm.cpp --- kosaraju_algorithm/kosaraju_algorithm.cpp | 105 ++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 kosaraju_algorithm/kosaraju_algorithm.cpp diff --git a/kosaraju_algorithm/kosaraju_algorithm.cpp b/kosaraju_algorithm/kosaraju_algorithm.cpp new file mode 100644 index 0000000000..8b969d461e --- /dev/null +++ b/kosaraju_algorithm/kosaraju_algorithm.cpp @@ -0,0 +1,105 @@ +//Strongly connected components(KOSARAJU ALGORITHM) +#include +#include +#include +#include +using namespace std; + +//dfs to store vertices in a stack as per their finish time +void dfs(vector* edges, int start, unordered_set &visited, stack &finishStack) { + visited.insert(start); + for (int i = 0; i < edges[start].size(); i++) { + int adjacent = edges[start][i]; + if (visited.count(adjacent) == 0) { + dfs(edges, adjacent, visited, finishStack); + } + } + finishStack.push(start); +} + +//dfs of a transpose graph +void dfs2(vector* edges, int start, unordered_set* component, unordered_set & visited) { + visited.insert(start); + component->insert(start); + for (int i = 0; i < edges[start].size(); i++) { + int adjacent = edges[start][i]; + if (visited.count(adjacent) == 0) { + dfs2(edges, adjacent, component, visited); + } + } +} + +unordered_set*>* getSCC(vector* edges, vector* edgesT, int n) { + unordered_set visited; + stack finishedVertices; + for (int i = 0; i < n; i++) { + if (visited.count(i) == 0) { + dfs(edges, i, visited, finishedVertices); + } + } + unordered_set*>* output = new unordered_set*>(); + visited.clear(); + while (finishedVertices.size() != 0) { + int element = finishedVertices.top(); + finishedVertices.pop(); + if (visited.count(element) != 0) { + continue; + } + unordered_set* component = new unordered_set(); + dfs2(edgesT, element, component, visited); + output->insert(component); + } + return output; +} + +int main() { + int n; //no.of vertices + cout<<"Enter the no. of vertices : "<> n; + vector* edges = new vector[n]; //using a adjacency list to implement + vector* edgesT = new vector[n]; //transpose of a graph + int m; // no.of edges + cout<<"Enter the no. of edges : "<> m; + + for (int i = 0; i < m; i++) { + int j, k; + cin >> j >> k; + edges[j - 1].push_back(k - 1); + edgesT[k - 1].push_back(j - 1); + } + + unordered_set*>* components = getSCC(edges, edgesT, n); + unordered_set*>::iterator it = components->begin(); + + while (it != components->end()) { + unordered_set* component = *it; + unordered_set::iterator it2 = component->begin(); + while (it2 != component->end()) { + cout <<*it2 + 1<< " "; + it2++; + } + cout << endl; + delete component; + it++; + } + + delete components; + delete [] edges; + delete [] edgesT; +} + +/*INPUTS +Enter the no. of vertices : 6 +Enter the no. of edges :7 +1 2 +2 3 +3 4 +4 1 +3 5 +5 6 +6 5 + +OUTPUT +6 5 +2 3 4 1 */ From d1994bacd3edc8db7723ef5f882e5d896e4ee7b8 Mon Sep 17 00:00:00 2001 From: j-shreya <53999364+j-shreya@users.noreply.github.com> Date: Wed, 1 Apr 2020 23:28:08 +0530 Subject: [PATCH 20/56] Aggressive cows (#2543) * Create GENERIC_TREE_LOTRAVERSAL.java * Update GENERIC_TREE_LOTRAVERSAL.java * Revert "Update GENERIC_TREE_LOTRAVERSAL.java" This reverts commit dfdd3095201cbf35c1ee673a6332a0eaf4960a88. * Revert "Create GENERIC_TREE_LOTRAVERSAL.java" This reverts commit 2c87bbb08c1e7f312d3e9410b7ff5423d25f1458. * Create Aggressive_Cows.java * Update Aggressive_Cows.java 1. Multi comments made 2. Extra spaces and lines removed 3. Indentation corrected --- Aggressive_Cows/Aggressive_Cows.java | 76 ++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 Aggressive_Cows/Aggressive_Cows.java diff --git a/Aggressive_Cows/Aggressive_Cows.java b/Aggressive_Cows/Aggressive_Cows.java new file mode 100644 index 0000000000..1cdb49723f --- /dev/null +++ b/Aggressive_Cows/Aggressive_Cows.java @@ -0,0 +1,76 @@ +import java.util.Arrays; +import java.util.Scanner; + +public class Aggressive_Cows { + + public static void main(String[] args) { + + /* in this problem we have to maximise the minimum distance between the + * cows since minimum distance is being linearly checked we apply + * binary search on minimum distance */ + + Scanner scn = new Scanner(System.in); + int nos = scn.nextInt(); // input for no. of stalls + int noc = scn.nextInt(); // input for no. of cows + + int[] arr = new int[nos]; // storing the position of stalls in an array + + for (int i = 0; i < arr.length; i++) { + arr[i] = scn.nextInt(); + } + + Arrays.sort(arr); // to sort the positions of stalls in ascending order + + int finalAns = 0; + + int lo = 0; + int hi = arr[arr.length - 1] - arr[0]; + + while (lo <= hi) { + + int mid = (lo + hi) / 2; + + if (isItPossible(nos, noc, arr, mid)) { + + finalAns = mid; + lo = mid + 1; + + }else{ + hi = mid - 1; + } + } + + System.out.println(finalAns); + + } + + // function to check if a particular arrangement of cows is possible or not + private static boolean isItPossible(int nos, int noc, int[] arr, int mid) { + + int cowsPlaced = 1; + int lastCowPos = arr[0]; // position at which cow is placed + + for (int i = 1; i < arr.length; i++) { + + if (arr[i] - lastCowPos >= mid) { + cowsPlaced++; + lastCowPos = arr[i]; + + if (cowsPlaced == noc) { + return true; + } + } + } + return false; + } +} + +// SAMPLE INPUT: 5 3 +// 1 +// 2 +// 8 +// 4 +// 9 +// +// Output: +// 3 From 537ef7693a77aefa386dd29b5de969da60b170aa Mon Sep 17 00:00:00 2001 From: shreya kapoor <31164665+shreyakapoor08@users.noreply.github.com> Date: Thu, 2 Apr 2020 16:40:17 +0530 Subject: [PATCH 21/56] Logistic Regression in Python (#2636) --- .../Logistic_Regression.ipynb | 418 ++++++++++++++++++ 1 file changed, 418 insertions(+) create mode 100644 Machine_Learning/Logistic_Regression/Logistic_Regression.ipynb diff --git a/Machine_Learning/Logistic_Regression/Logistic_Regression.ipynb b/Machine_Learning/Logistic_Regression/Logistic_Regression.ipynb new file mode 100644 index 0000000000..669cfdb7fc --- /dev/null +++ b/Machine_Learning/Logistic_Regression/Logistic_Regression.ipynb @@ -0,0 +1,418 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import pandas as pd\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "plt.style.use('seaborn')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(500, 2)\n", + "(500, 2)\n" + ] + } + ], + "source": [ + "mean_01 = np.array([1,0.5])\n", + "cov_01 = np.array([[1,0.1],[0.1,1.2]])\n", + "\n", + "mean_02 = np.array([4,5])\n", + "cov_02 = np.array([[1.21,0.1],[0.1,1.3]])\n", + "\n", + "\n", + "# Normal Distribution\n", + "dist_01 = np.random.multivariate_normal(mean_01,cov_01,500)\n", + "dist_02 = np.random.multivariate_normal(mean_02,cov_02,500)\n", + "\n", + "print(dist_01.shape)\n", + "print(dist_02.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAfIAAAFcCAYAAAAzhzxOAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjAsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+17YcXAAAgAElEQVR4nOydeXgUZdb27+7q6iUbSSCAJCxhdRsdXnVwxwW3mXdGHRccRhREYWSU0c/XmWGUccFxRsQwBgUlSFAgbGFVlE0goAQUiCgRCLuyKNk7W2/V/f1RXZWqrqXXdLbzu65c2lXVTz1V3fSpc55z7mPw+Xw+EARBEATRLjG29gQIgiAIgogcMuQEQRAE0Y4hQ04QBEEQ7Rgy5ARBEATRjiFDThAEQRDtGDLkBEEQBNGOaVFDXlZWhhEjRmDhwoUAgHPnzmH06NEYNWoU/vKXv8DlcrXk6QmCIAiiw9NihryxsRFTp07FNddcI27Lzc3FqFGjUFBQgL59+6KwsLClTk8QBEEQnYIWM+Rmsxl5eXno3r27uG337t249dZbAQA333wziouLW+r0BEEQBNEpMLXYwCYTTCb58E1NTTCbzQCArl27ory8vKVOTxAEQRCdglZLdgtVGdbj4Vp4JgRBEATRfmkxj1yNhIQEOBwOWK1W/Pzzz7KwuxbV1Y1xmJmcjIxklJfXxf28rQVdb8elM10r0LmutzNdK9C5rjcjIzms4+PqkV977bXYsGEDAGDjxo244YYb4nl6giAIguhwtJhHfuDAAbzxxhs4c+YMTCYTNmzYgOnTp+Pvf/87li5dil69euGee+5pqdMTBEEQRKegxQz5pZdeigULFii25+fnt9QpCYIgCKLTQcpuBEEQBNGOIUNOEARBEO0YMuQEQRAE0Y4hQ04QBEEQ7Zi41pETBEEQRGvy448/IDf3LdTUVIPjvPjFLy7Dn//8DCorK/Dii3/DBx8ok7Qjpb6+Hq+88gLq6+thsyXg5ZdfQ0pKl5iNL0AeOUEQBNFmcbo5nK9uhMPliXosjuPw4ot/xahRjyAv7yPRaOfn50U9thrLlhVg6NArMHv2Bxg+/GYsXPhhi5yHPHKCIAiizcF5vVi65ShKyspRZXciI82GywZ0xchbBoIxRuaDfv31bvTp0w9Dh14BADAYDJg4cRIMBiMqKyvE4zZu/AyFhUvBMEb06zcAf/vbC/jpp58wdeoUGI1GcByHf/5zKgCDYlvPnheI4+zd+zUmT/4nAOC6627EX//6TOQ3RAcy5ARBEESbY+mWo9i857T4+nx1k/h61IjBEY35ww8nMWiQ/L0Wi1VxXFNTE956ayaSk5Px5z8/gWPHjuLrr3fhqquGYcyYx3H48CFUVFTgwIH9im1SQ15ZWYnU1DQAQFpamuxhIZaQIScIgiDaFE43h5Iy9e6YJWUVuG/4AFhYJoKRDfB6vUGPSklJweTJzwEATp06gdraGvzqV1fjH/94HnV1dbj55ltx6aWXISHBptimRaiNwiKB1sgJgiCINkVtvRNVdqfqvuo6B2rr1fcFo2/ffvj++1LZNpfLhePHj4qv3W43cnKm4ZVXXsc778zBxRdfCgDo338g5s9fjMsvH4r33nsHn332ieo2Kd26dUNVFe+FV1SUo1u3jIjmHQwy5ARBEESbokuSBekpFtV9aclWdElS3xeMq64ahp9/PocvvtgOAPB6vZg9eyY+/3yTeExjYwMYhkHXrt3w888/4dChg/B4PNi8eQOOHz+KG2+8CU88MRGHDx9U3SblV7+6Glu2bAYAbNv2OYYNuyaieQeDQusEQRBEm8LCMhg6OEO2Ri4wdHC3CMPqgNFoxFtvvYNp0/6F/Pw8sCyLq64ahrFjn8DPP/8EAOjSJRVXXTUMjz/+CAYOHIRRo0YjNzcHkyf/EzNmTIPNlgCj0YhnnnkeTqcT06e/Ltsm5f77H8LUqVMwceLjSEpK9ifIxR6DryUD9zGgNfrPdqa+twBdb0emM10r0Lmut6Nfa3PWegWq6xzolhp91np7Idx+5OSREwRBEG0OxmjEqBGDcd/wAaitd2JAv66oq21q7Wm1STr2Yw1BEATRrrGwDLqnJcBqJr9TCzLkBEEQBNGOIUNOEARBEO0YMuQEQRAE0Y4hQ04QBEEQ7Rgy5ARBEESn4ccff8Dzz/8FTzzxCB577GHMmDENLpcL586dxbhxo2N+vi1bNuO2226QqcfFGjLkBEEQRNvG4YjJMPFuY1pSshe7dn2JAQMGtcj4ApTPTxAEQbRdHA6k3vtr4Msvoh4q3m1Mhwy5EEOHXoGnnhof9dz1IENOEARBtFlss3LB7t0DTJ8OjJ8U1VjxbmOakJAY1XxDhQw5QRAE0TZxOGBZvYL//8WLgUcnAJbIGqbwtF4b05aE1sgJgiDaCzFaK24v2Gblgj3k7yhWWgrbrNyoxot3G9N4QYacIAiiPSCsFTsj68Xd7pB6434sqwqjuv54tzGNFxRaJwiCaAcIa8W2Wbloevb54G9o58i8cT/soYNRXX+825h+8slqrF//KY4eLcPrr7+Kvn37YcqUVyO7ITpQG1MVOnp7wEDoejsunelagQ58vQ4HUm8fDvbQQbgvvAg1m7YjI6tbx7xWAHA6kXbjMJhOHFfs8mT3R/X23VGulbdtqI0pQRBEB0PqnQpeKV6PvWfXZmAY2AuWyzalpyehqqpe3E80Q4acIAiiLaO1VvzSC600oThgMoELFFHJSAbXUSMQUULJbgRBEG0YrbViTJ/eSjMi2hpxN+QNDQ146qmnMHr0aDz00EPYsWNHvKdAEATRPnA6YV1aoL5v/vzOk8FO6BL30PqqVauQnZ2N5557Dj///DMeffRRrF+/Pt7TIAiiJXE4AKtSMYsIE5W1YoH09CRaKyYAtIIhT0tLw+HDhwEAdrsdaWlp8Z4CQRDBiMYQ++uda1Z/Fn1mcWd/IFBbKxbISAZozZhAK4TWf/Ob3+Ds2bO47bbb8PDDD+Nvf/tbvKdAEIQeUQqPSOudW3MeBNFZiHsd+Zo1a7Bnzx5MnToVhw4dwj/+8Q+sXLlS83iPh4PJROEjgogbr70GTJnC//eFMDOjHQ7gyiuB0lLgkkuAvXsj98r15hHMU+/snjzRqYh7aH3fvn24/vrrAQAXXnghzp8/D47jwGis9VRXN8ZzegA6sKiEBnS9HZewr9XhQOqiArAA3AsXoSbMJhW2nGlIKvVrWZeWov6Vf0WmwqU3D53QfUZGMsp/LI9daL8N05m+x0Dnut5wBWHiHlrv27cv9u/fDwA4c+YMEhMTNY04QRDxRVV4JFRiqI2tN49gofuYhfYJop0Qd0M+cuRInDlzBg8//DCee+45vPzyy/GeAkEQakRpiPW0sQPPE/E8JPtU5xZsP0F0QOJuyBMTE/H2229j4cKFWLJkCa655pp4T4EgCBVCNsRq6NQ7W5csajaoISSw6c0jaMRg+vTIIwotSSdrP0rEF1J2IwgidEOshb/euap4r+LPXrBcrHcOGvbWm8fihbCslNdUy7xuhwNYskR7f2tB2fdEC0Na6wRB6AqPCPt10at3FggIezdNnKRMRtOZhyV/LhLnzJZtk7a1tM3K5bPlNfa3Fp2t/SgRf8gjJwhCNMRafzBF/8wfUiKd1jyy+sCyaYPquNYliwC7PeTQflyhNXsiDpBHThBEy6ORwKbqlasRLGJgNsNesFze6jLg/bqKcy1Ud6728KLrlVP9OxEB5JETBNHiRJVIBwSPGFit/H8HD9aMKGiuz7fUGnYoVQDSCIHDgdS77ySvnQgbMuQEQbQs0SbSxQKdEHdL1Z0HfXgJeICw5eaALdkHW25OTOdBdHzIkBMEET16a88hZrS3JJrr8y21hh3Cw4vsAcLhgG3+XH6u+XnklRNhQWvkBEFER7BuZ9KM9tZYA9ZZnw97DTtUgq3pu93yB4imJjAVFfxbKypgy81B0/OTo58H0Skgj5wgiKgIOTTdSvXUmiHu3JyYScoqCLKmb5szS/4A8f678jmTV06EARlygiAiJ4zQdEzWosMtH9MJcUuNqUBc1OBUIgRMU5P8td8rJ4hQIENOEETEhNxkJRZr0aF49IGGXmt9fuM2GBvVOyu2dAKeWoRA9bi898grJ0KCDDlBdCZiKYgSRpOVqLqqScfQ8+gdDuCmm8TmKgA0Q9zmzRthcLvBde+OqqJd8UvA04kQKEhKAjyelpkH0aGgZDeC6CwES0oLE73yqqZnn29ObFMz+CuWhS4G4597MHlX26xcYPdufu17yybULFkFdOmiOxZz/jzM69ai6f/+HuJVR0lgEpzHA+PZM+JLb68swCR5iOjA/dSJ2EEeOUF0EmJaLx2svKq2VgyDqxr8ssNhzSOoRy8xzrb8PLB79yB9+DDt6EDZ4ebX80JILItVJCMwQjDkIrhvHiH+cUMujLk0LtHxIUNOEJ2BWNdLB6kNt+XN5h8acnN0u5mFNI8QQvhSQy+WcZ09q0wYczgUHdSYinLYZs7QPT91LyPaMmTICaITEIs1ahl65VWZvWFZuwoAYFm7Cvb5Bagq3ovG8U/KhnDdcVdIa9GhKKQFGnrxvQFlXIHeuLhdxyuPufJbON499TEnQoAMOUF0dMJISosFsoeGw4dgXr8OXGZvsNu3yY5ji7YCHKc/mNPJh+pVkCmkaWSBy8q4nE4+CqB6nIZXHutIRjjePUUCiBAhQ04QHZyoG5YAoXuGGg8NtpkzIpuD2w1fYiKqinahwe/RN4yf2Jxd7vEEzQIXvXK3G64Rt2seZ122WGE0Yx3JCMe7bykNeKLjQYacIDoyOl5oyPXSYXiGWg8NCXPfi2gOtjmzwJYegPmTNTD7PXrz9q3gsvrwyWAWC79WX1QMLqu36hhMRQVsOdOQet//wrx5o+oxXFZv2D8skIf6HQ5YVhbKjrOsWB65hxyOd692LIXZCQ0oJZIgOjJuN5CUhKqiYsBsVu4PdY3a7xnq6pDrZLJ7ExLgTU2F6cQJeLIHwD5/YfN8tOYgMaS2eXlgKvkkNlmJm6Dj7vGgdtFypI9+EPjhB+U1zMsDU1uDhvETYR81GrAo7wXXN1uWJW7LzQFbdkh2DFt2SPs+BNGRD0fX3ZabIz9WKKmLUekg0bEw+Hw+X2tPQo/y8rq4nzMjI7lVztta0PV2XDLefxuYMgX1k6dE1gzE4UDq7cPBHjoI94UXoWbTdm1D4vGAOXVCdZc1fy4S5swWXyvmo2IEbdNeR9L0/6iOpzoXjwcZdeWoqqqXH+x0ImXsaJhOHIN78IVAYgJq1m7QN4i1teh61WUw1lQrL7NfNqp3fCV/f00NUv/we21DK7mPutfgH6vrZYNhlHjgXLduYCoqZPetM32Pgc51vRkZyWEdT6F1guioOBzAkiUAIk/UCmuNWCuTXSXRTTYftdC9pK2nGqpzMZmAwYOVKm7rP4XpxDH+fWWH+J7f/tahqjgcSH3gd+BS0wAAXFqabLfz9rsUIfj0m67WXc8OJ08hZdxomREHmkvqKMxOqEGGnCA6KLZZuUBpKQBtERVdYpTtHsyIqSV12XJzROOlRUh16BqlaZblS5B6913agjHflIA9eRwAwFTLvXLz9q1AQ4N8rmfP8uOq3Z8QepOL1NaC3bVT83KEMDtlsxNSyJATREckmBEOIYEtJtnuekZs8UKgtlZcBxcTyZxOJMx9X/U93uRkeC6+BFUbi+BLTAyqRa5VmsYePQK2ZK+6QtxKnT7i4O+BqBoXEDlQvT9BxHOk3r0tbzaMbrf4umHceLj795dfk1+5DtOn686T6DyQISeIDkgkXrCMcLxIPVSMmFBG5rz9Ll4Bzp9QxpYd4mu+3W5w6Wmqw/lMJpi+L0Xi1H+CLT0A25xZ2ucOoUFJYBa6lmCM4rL8qnFqkQNF+DtIb3Ixwc7hEIV0BKxrVoI9flx+buF8i5XlckTnhAw5QXQ0QtBBD1oGFYYXqYvUiGX2BpfZu7mMbNsWRXlXwswZsOVMUxgvcVr+MDe7u1h7/oIBlVxDQ4CqnID48OB/n5437snKQtXGItFDtqxeAVu+ch0/0vC32sOX7vJCaSnVmBMAKGtdlc6UHQnQ9XY4JNnj6elJiixu86oVSJr2uvi6/vnJaHp+cmTnClJyJT0u9d5fw3nzCM1MdAGfwQBDGD9LYia3w4GMjGS4r79Bnj3udCLtuitgUilLAwCvxYrK0qOwzX0PSf95TbG/YdwEOB8fD0B577TwpqbBWFMderWA04m0G4fBdEL5AOPJyoJ9USHg84rZ9wJBKwk6EB3+360EyloniM6OxAtWZHFLdNAFEmbOAOx2/kWYOuBhCcXs3aObiS5g8PnAJYX+Q2ZZVch3W7v7TuA//2leMhCuxe2GQee6jE4HUh75g3YUY8UyXoBG5d6p4emVKWa8h5wcqBcBWb4G3KDBsux7gZjo5hPtHjLkBNHeiKL0SC18a3Q4kPLYw/qGWeWcIUmIOhzy/t9BMtFFWBOqiopFYxbYcEV26KGDSBk7CmzJPmAWv2ZuWbGcN+x+LXbm/Hnd05l37oD9nfdRtW0nPNkDZPt8aemAx6OZOCdIxgp/rv/9nZjxHrKhDbaOznGxyVkgOiRkyAmiPRFNIw2dtXNz8ZewzXhTaZj9hlitzlt1nV1q8P3vU9NZDwZTXQ3zuo95Q9atO8ybNugeb/7yS/5/yssBSOrFc3M0owCuq34l/r8BQOJ/XoP5k7UKr9d04hhss2dq3jvLpvWixx60Zj5S/B574Fp/w/iJ4eUsEB0SMuQE0Y6IqpFGQPhW6uUa3G7YFuQDkGddp977a14uNLDOW00oJsDgi3NVSQhz98uG6+JL9K91Xh4fMh95D+zv56Nqx1eoWboSTQ/+QXGswedVH+OD9zWjAGxJifx18U4kBvYv92Ndthj2+Yu0k//cbs2Hlpi1jZUkCgoIuvNSaVmi89Eqn/7atWsxd+5cmEwmTJo0CTfddFNrTIMg2hcBXnDTxEnhJTkJuuT+sQI9R8HgiYbH5wO7dw+Mp07Kz+nzqdeoezy84c7NQdPTz0rC6eWKqbAnT8BrMOhOl6koR8qYUWD37UWXMaNQtfsbcH37IfGlF0K+ZKaqSrGN65YB5933IuGDObLtRg9fv904YSIcY8Yp3xegxS7icIgPLczxY8r94MPfYX9eAeiVFEYkv0t0GOJuyKurq/Huu+9ixYoVaGxsxMyZM8mQE0QwBGMRYtONYOj18AYAy4pl4APOGgZexaAY/cclzJzBG/Ug4XRjCJnp7Fe7+DmcPQPbjDcBsznsMH0gTEU5LMuXaJ9zy2Y0vPhKs9HVy8x3OHiFuAa+MoBLS+Mz5s2s/DinK7rwd5CSwmgfEoj2TdwNeXFxMa655hokJSUhKSkJU6dOjfcUCKJ94XDwiVsNjbLNEXnlQEhCKVqiKJYVy2Fwqa/3Cp630eGA7b13Zft8RiMMXvXwdyAN48bD+fgEWPLnIlHSaCXx7bc0W5WGi0EisRoIe6Ss+SHJv1wgK2eTGHbbrFywJXub33v8OMzr1ykawohjeDyhlesF4l8WkSIrLaQ18k5N3NfIT58+DYfDgT/96U8YNWoUiouL4z0FgmhX8MZin7KlZqRrr9K18qJd8GRlhfxWtuwQXHfcJV8nVsn0ZprkDx2hGnEAsGzeyCe4BYT+DRwHrlsGGh59LOSxtDBynP4c/IpvipwEaR6ASr9yQJncJo4RKBITTvWBSla7tLSQ1sg7Ob448/777/smTJjgc7vdvlOnTvmGDx/u83q9mse73Z44zo4g2hhNTT7fRRf5fID638CBPp/DEfn4brfPd/iwz/fttz7foEH8mOnp2udTO+fUqfrHh/rXpYvPt2ePz3fZZT7flCnqxxiNPp/Vqj1Gz54+X48eym2Az2cyhTefl1/2+S65hP//Sy7hr1m41tde07/u115r/vyEMbp3b97X1OTzDRum/tk1NUX+ebbkWESbJe6PcV27dsXQoUNhMpnQp08fJCYmoqqqCl27dlU9vrq6UXV7S9KZFIQAut62jC1nGpIONq8JN4yfCOdYeSIWV9UImFyq7w/pWtMu4M9z5Aj/WiVBDAC4zCzUFiwHzObmczqdSJuXr7pG5zOZUP3JRhhra5Dw6kswl36nOq6PZWFwu+FJ7wZHwTIkffstuFM/QDVY7PWqerKNj0+A44GHkP7sn+H7/ntI0+h8P/3Evw7SYEVxqv++3dyPvLQU9VNegeXj1WABuD9awOcKaLzX88E8VD86AbZ330aSvwMd/LXs7oWL4KxtQNLu3ah/5V/aYfggSyZBP9swxgqLUNX8Ykx7+ncbLW1e2e3666/Hrl274PV6UV1djcbGRqSlqTdIIIhOjUoHM6HcSLXpRgTja53HazYrQtiO3/wO3KAh8nP6w/SuK69SDG/weGDe+jnc/3MVTAHLArLj/N2+TCeOwfbRPACAsakRXK/MkC/FsqoQXR79IxBgxAEoXkvxJibCccdd/PXdcRfcAwaiZuEyVG3eoWjcYpuX15xsWHYY7JEyxXiNEybKStLUWqiyhw6KJXmaYfgYqLXFciyRaHQMiBYj7oa8R48euOOOO/Dggw/iiSeewIsvvgijkcrZCSKQmLQR1ULyg6yq9uZywbpssWybeftWIHBt2WQC1607TPu/UT2NdWkBbLNnylpz6iFkyBtcLnC9MnUV3WTvq6wE89PZkI6V4u2SCuboUQAAu+crsMeOwlT6HcybNyi7jlUGV6Uzb1wvPmjZ5szSzLAXEgNln6eWyE4kxHIsCS3ycEBETatY0IceegiFhYUoLCzErbfe2hpTIIi2TSzaiOokU0kTsLTOwzQ1yV4LXb0UYwX20B4/sblV6a23wfLxatnx7v79UVW0S7MjmYBpfwnMn36ie0w0uHtl8nKqx/glBaayEgCf6GZdsij88bKzYZ9fwGeQh1AZICAYWlWRnQiJ5VgiLfRwQEQPucIE0RaRZpZvKw6/jWgQ3XTxB3ntKtjnFzT3Cn9svO6wibk5zQ1WhLECGomYt22BectmAIB19QpFCJo9fhzmdWth+Wyd7rmMbjeYM6d1j4kG09kzYFWkXxWZ+RuL4A1h+YI9cQLmT9bwyw7C5xdCVYDwgKQqshOJsVRZKomF4W2RhwMiJpAhJ4i2iFBulNkbyc89rb8uHuh5S5TGMH26YmjZD/LhQzCvXyeey7p2pexYLjVdbF7SOP5JGJxO2PJmq44lwJYdAntU7uUGYl1aAEMIoepw2pmGiwEAq9I2FADYouZcBPPmDTBKEuUaHp+gaZwTZrzJP+gIn9+gwbAvX+Mv9SvWrIO35b0X3TKK5DsQsyWZAN38lng4IGIDGXKCaMMEXZMM9Lz94jFiffPixZrNTgTE0G5ujkKXnKmpgvmTteC6ZoiSrpY1K/kxwwgfCwjJYM7ht4BplFekhGOyuR49UfX5F2gYpx9BiBSpfrwi4lC0DfZFy1W7shk9Hthmz2zeIK3/HjQEtctXK/Xai4qBpCTVeYS0jCL9DsRiSSZwTLRwvgYRNaQiQBBtlRC01aWGvunZ50XxGJHSUpmUq+YP8swZsM19X3UatjmzYVs4H8y5c83Hz8pF09PPNquNOZ2AxaJQYwuE3boFDf83GdblixX79JXX+bX1uvwCUf6U69kLls83BXmXzngDB4mRAzWsSxYBbrfyfh05DPP6T9H05NMKvXoAsOXnoemZ/1OWfEm17qV4PKhdvlq5XUBYRtEo+5J9B2SfiQuwmNXHCoJszImTSB62jUMeOUG0UYKuSQYmH9XWwlK4VDGOGALV89aWFgCJiar7DF6vaMRlY3Jcc/j/2afBZfSAZcNnutfElh1CyiMPKRLpQkGQP+Uye/MG0WKBfXGhmDTX+LvfA6xWZbcSk0aDEwBoHD0W9vkFsKrcTwCwLl6o2Z6VqaqCLWca/8LfBlZ/IkF6kZtM2jkPgd8B6WcSbElGi8AxPR5Z17yw8zWIFocMOUG0RUJYkww09CljR6l6mOJDgJCAta0Y7v79ATRnkNsXLkXth4vhvuRSVBXtksivFsNnUv5QSx8sbLk5YEv2wjb7HbhuvT3opZl3RS7LbF28kNeddzoVrT0tmz4DQixzA/gHFNcVV6qfZ9GH4Hr0hH1xIZ8EGBBCd956O6w6jVdss2fyLVjvvpNvqhKLRDOVJRath71oysQUY86ZFfxBg2hVyJATRBsk6JqkiqFnd36pOZ51ySLRWzOvXyfWSIte7pCL+Nrp0gPNyW8DBsH8yRow1dXaY9bWiuImtvlzYV25LOi1afUODwaX1RvO4beALdknf4jw36dIvHzTt/tVtxu9XqQ8/gjv/av1Af+iCPYPF/NGXkX7nXE4kPLoH3iN/JK9ka8lOxxATY162ZfWw15tbeRlYpTU1i4hQ04QbY0QEpZURVzUGpM884w8BBrOj7/DoVkDLoxpe2eGKJTCVFbAF6YMajB8/lC5J3sAamd/ANuShc1zPP8zEt75r+r7Qn1UMLrd8KakqO5jd+1E6m/vkD0siPuEbP+sPrAuUf+szDu/EP9faMISFv7ExfThw9SXWKZPV33YS3ns4YjLxCiprX1i8PlasL4jBrSGtm5n0vQF6HrbHB4PmFMnNHdzPXsh7ZbrYNIonZIxcCDKtxaLyUi2nGlI+s9risOcN94Ei8TrrJ88BfD5VI+tnzxFbPHZ9cJ+MEqyz71WK4wOBzy9MmE6eyb4/MLA3bcf2FMnNV9HiicrC/ZFhYCZVU3W41LTwNQooxKeftmoXvMZul1xKQwhPMCI900giGa51mflvvAi1HyyCRl33gT4VemkeFlWJtDjvvAi1GzaHjwhzelE2o3DVL9Xnuz+qN6+u1WT2tr8v9sY0ua11gmCCEKw5CeLBfb8hYrWoVI82QP4sqZ165qTkXQ8fXOxPCyvp24mRgVypsmMOMD3IgcAJsZGHABMAUY78HUkNE6YCPvyNeAGDeZD6Nu2Ko7xpaWi6pMN8FltqNpUhMbHngAAuG69DbYF80My4kCAVx7QDlWBwwHLyuXK7fB7yHmzgXXrFOVvzit/pZDDDdmjlooQUVJbu4I8chU605MfQNfbHtHy1qTUT/MZ3DEAACAASURBVJ6CpNdf5a/V4QBMJlVP35o/FwkqJWONEybCMWacYjvARwW6XpQtGu5QCMVL53r0RN1bb8OyegVshcHX26PF0y8b1Tu+AiwW3Xvq7tMX7A+n4Lz6OrDf7IXR4YDXYgHXp69q8xQtBK9cOFf985Nh2bJJ0aEs2Ofrye4PU8k+uK++RhYKFzrJqR3f2h51tHSEf7ehEq5HTumGBNHeCFGIxbpkEfDSC7J2loo6ZqcTZhWZUoBvANLw4ivqP/6VlWG3BdXy0j29MmFfvEJWH57y1J/CGjtSnLffxXuatbW6+uqmH04BAMy7vhTr3Y1OJ4xhGHGAz7pvemy8mI9gy88DU1Ehq/XX8sa51DTUrvkUMPO14elvv61Yzza43doPYORRd1jIkBNEe8MfAgUANDQi+U+PoeHlfwEs/8/Z2ysL8JeMpbvdCtEYzbE0ziUiWdO15efJZEuD0fT7B8B8tx9mFcPH9coE17tPs7pZfT241C7NvcBbEMvGz9D4/GSkjrwHzhtvhumkem6CIeC/odL44Ci47rsfcLkBMwtvryzY8mY3Z9r7lfSkgj+2Wblgyw4rxmJqqmFe9zGa/u/vfEh+wQLVc+o+gBEdEjLkBNHekCiE2XKmgT16BKbS75RG2uEAbrkFllo+HKmqDuevxdZLuhLGErx6ALo11GqYi7ZqGmZzyV6k/v43qFm+FujShTdkJ0+GNX4wuMRE1L2fD7AmeHtlwrpgPhLmzObXufNmg923V7MVazSYv96Fhn+9gdSH7uXvnc8Hy+qViuOExilNk/4frAXqBhoAEubMRtPTz/IPWOvWoaqqXv1A8r47FZTsRhBtHWEdWqU5il69sG1WLvD112DLDgHQVocL1GpXQyYwwjCw5y8Sk75CgamsgOPe+9F0/4PiNq53b9QsXArHvfeB/aYE6cOH8XXp8+fqjsWZzbr7VUlNg/u6G+C+eQS4vtlg/Ult1oUfimFsQ2CvdQBcUvC1Sh/DoPGe+wHwHnjN0pWoWbAEVTu+4kv08maL986WmyN+HoEkzJwBVFUCScmoWbgUNQuWwBPQZIVLS+OXNEwmYPBgEmkhAJAhJ4i2jWBoa2sVEp2aEq5+WVC1dVZVdTjBQGvJgAYKkjQ0IPnZP/NZ2GFg2bwB5q1bxNfMjz/CtHcPLB+v5V+fPYuUR/+gaNwSCONyBT1X00jeoFZt3gHPRRfD16WLeC186Jo3pkanU1dv3VgfPLnKwHGwfLENAMB+WwL3/1yFxP9OB9cvG1xmb7HpimXFMiTMfU/7XA4HUn93J0zfH4Cp1P93+kfZMeyJ47DNmRV0TkTngnn55Zdfbu1J6NHYGPwfbaxJTLS0ynlbC7retostNwe25Utg+mYfzLuK4bNa4bnmOsDhQNILf5UZPUNFORy/fxCpD/wOhvM/w/bxGsV4TEWF6hiGinIYqqthW7GseT8AOBxIv+5Kce2Yqajg57J7F2Axw6AicsJ17QauR094ExPB1DX3LvdarGCqq+Tz2V8CRhIFMP74g+Y6dOPYx2EoPw+jZEwtDI0NaPjnVFiXLoJ19QoYy8vhMxrR5YlHYfzhlGIeimuwWuF46I8wayi/BSKU4TEVFTDtL4F51074rFawX++GzR9KZyor4bXZ+Ix3kwkGFQEfY20NDAAM58+D3V8CY02N8pgzp+F4ZCwSUxLazfdYxF89EQnt6d9ttCQmhpffQOVnKnSmMgeArrfN4nAg9fbhYA8dhNdshtHlEsU9bO++rSvswnXtqtkLXChFChyD69YNTEWFTEDENu11JE3/j+z94lz69QdsVtS9N0/MOIfTBUvBR7od0CLF0y8b9g8LxKxteDwwnjyB5H88D+bHH/mSrLVrUFXP/9hzPS5A6p03i4ljnM0Wlowrl9YVTLX6PZQdl5oKRmJwxfsz+EIAPtXENQBoGD8RzlGjNe9X47jxcDw+Qf2cfbORcUFa+/geC0jzLCJIxGs3/25jAJWfEUQHQRo6N/rDyUJSlFZXLkHYRc2IN4x9HE5BQMTtbu5Z7kfw7sU2pU8+rbpeLc7lJK8AZl6/TlR6S737LqAutj+2DeMnwjl2HOB0gRs0RObRmdd9DOZHPvxsOnEcKCwE9+fnAIdDkf0drhZ7KEYcgMyIA5L7o7EWLmDe9jnMXxUDAaI6AtZFH6Fh8j8BDQnZFiOI4lyk6FZPEFFBa+QE0RZR0UQXsKxdBfv8AoX6VuP4J1XFQARsBQvFtpbSdWLVc6wqhG3Gm0HXqwF+7VfUfy/ZC/Zoc4lZ44SJqCoqBtcrM+g4muNvWg+uW3ckP/c00NDQvEPtHk2bBpw/j9S771Jt6RprfFFkh7Nlh8F+U6LpsRsdDqQ89nDE44uEIdqjmScRgzlE3MiFCAoZcoJog6g1rxAQG3ZIM5Uze4MN6NAViMHl5A2h04mEue/rHsseOgjbgnzZNi4tTf3YssOw5UxTePgAwBZtBde9J7xdusDdtx8AXgucE5LPNPBc0Avuiy7hW6zmLxIzv9OHDxONgOo9ampC6m9G+B8otJPYoqVh3ARU7fgKtQXLUbVjN6q27QTXvbvqsc4rroQnKyui85iLvwTswXMCNAnTMEfT/jTouBE2ciGCQ4acINoaISi3CXrnAnqGX8Dg8yHliUcBtxtcOm+U3f2y4clUNzKB3rhWO1MASNAoq2IPHUTK+DFgD34vNjgxut1gamtVx/FaLKgqKobrrt+APVgK8ydrkPyXibwXBz6z3Zabo3uPQtVgd//iMr7ES+P6FXOThvS3bwXXL5svZxtyEcyfrAVz/rzq+9hv98OeX6CInkgRsuxrlq5E08g/iNsNbjevqx6OVy0hqGGWjttSXjO1Rm1xyJATRFtDaF6x4yvxx136V7Vjt7yJRYiSrQBg/mI7X8ss9CM/eQLOO38Nd//+APxtSjdtBxdQvyzAZfVGw7jxiu1GlRpsAXbXzpDmBvClXJwtQRRFsc3LA7u/RKZnbsvPAzweWYMPqWEMzHr3GdTz4E0Hv4dp316YzpwOaW5SJTv2SJm8N7y/3avQ5rVBMh+j2w3z5g3y6ElAcxZTyT64r70B7muuVwjTWFatQOrdd0bUBlXXMAd46y3lNVNr1JaHDDlBtDWE7mdDLoT75hGKP27IRXLRD7/hbwjw8lwDByuGNvh8sH0kD5lb16xsNuzHj8O8eQNql69W7YJVu2g5LJ9vCukyXFdchYbxTyq6celh8HiQ+sDdzV3UKpVr9II2eajLCp4LLkDNwmVovO8BAEDj/SNRs3QlaucvglWjw1goyHIDDvtFd44fh/mTNTAHzMeyZqXcYAZEL9iyQ7xgjJrRKzsEtmSfXCdAjYDtwQxzoIZAi3jNOg+ZgVElInKo/EyFzlTmAND1tmlCzSCWlKoJ+IxG1VrlYOj2rw7olW6d+z4SPpijOo7PaIQnOxvssWNhnd+H4JrmXNduqPrmoGaJXCD1zz4P24J8MBUV4Lp1Q1XJQYBh+GtxutDl3l/rLh1ojvv8ZFg+Xi2770IZn+LYyVPQNHES0m74laqmu6dvP8Bg0NR7dw8egpp1m0W514ysbs3f48DSLpXvg+xzlex3X3gRnL+9B0lv/lt9ztFkmAd8XwLh+maHXFferv7dRgn1IyeIjkIYiUq23BxlJ6wIjDgg8d7UPD9pr/TM3mC/2K45jsHrDcuIe00muIZeEVJjEqayArYZbwK1tUjIzQl6vG32O6JxZSoqYJv2ungt5k/WRGTEAcA2Z7bivmtl+luXLAI8Hjhvv1N1v/O2O2FfsFQWAZFGWdiyw0h57GHVNe/AtfBg4exAb11LcS5qr1n6fSEp2RaDDDlBxJMwkpZCziCurUXizBnq+/r0QVVRMW8YJGvuVZu3w3PxJfD06qX6NmvBAr4mXCMpTZzfYf1a6XAwejxgS/aGfHzCvDmwvfcOjC4XGsY+AS5Z24thHPIa8sSZM4Dyctn6djhwKSmoyV/Y3LEtAJ/fQHmyB4j3X+gyZ9FoG2v5fCMv6yp5UAoM0bO7i/ljpWHvwLVwu10/nF1bqwijc2lpqCraJV9K2VYsz8Ug2iz0OEQQ8SIcZauAH2dF1zIJtrzZMDidqn2o09OTwCVniJ4PN+RC/j0502D6vhRc9+6oKipuVkvzY82fi4Q5s5E+/GpU7f4G8PnkIf4wEuy8CN1jCKdNKNelCyxreSNsXbsKTBhCNAYAqXfdAueo0aoPI00PjIR5exGYn39SfT9jt8N04DvUFiplcC35c0WlNtOJYzCv/7Q5PO3xwJ6/CLBoNH6RGE01r1oqDITp04Hxk5Rr4XmzeQPsdCLlz+Nhn5Un+3ylbVQF2OPHm4V9APl3lbzmNg955AQRJ8Kp0Q05g9jhEJtysEVbRcEXMXQ5eLDyh1jSUIU5fx7mdR9r1qQzZ8/ANuNNZYhfyKzfthOeiy9FTf5CcD17qk4xlj8yXmPzaOypU2CP8GIqaklxwTD9cArWReotQ9mvdqN22WpUFe3SrAG3fTBHcb/VvGiZ9+zxIPm5p5XvCww1h/KgtHixqndtWbMSXFYfmNd/ClPpAZjXf9p8jqw+mi1opWH0lqonJ1oGMuQEEQ/CqdENI4M4kpKhQOlS27w83Zp02+x3lD/q/j7m5vWf8t26Dh1E7ap1isx5LgJNba9OKDfSdX/VsQBwGRmqa9LOO34NbtBgcIMGw758Df/Akj1A9n5fWjrfUlRCSGvToRhI4UFJZa1cpLQUKeNGq58vN0f9+xYwrvRPDKOTClu7gww5QcSBcAxuyHW3kZQMqbQ3ZSrKYRPW2FXGZJoalWPX1CD17jtFNTfLqhXgunVXeKOMWne0Lqna84N+TXo4oXc1Akt02APfgsvoofCmzdu38ip4QkLc+k9hOiFP3DOdOCZvKRqs1EriPQf9nKRJYll9NNfVzTu/UN2ekPee+vcthOQzUmFrf7SKIXc4HBgxYgRWrlzZGqcniPgSjsENo+42EqGNQG9c3D4vD6it1ZeGFcauqUH6TVeDLdkn1kOzZYeQMvaPQdXlAICpVbbmjBeBDwJGl0vUMw80YOnDr+aT/c7/HNpnwjCw5y+C+5JL0eDPVWgYP1H0dqVr08GWS2RoeNEoLUXtomWo2rwD7ksubU5W21YsKvcJhOxZkwpbu6RVshhmz56NLkG0lgmiPeB0c6itd6JLkgUWVj0krGdwFTW6/h9tTUJQc7MuWaSeHOd0wrp4ofqwFeVIv+FX8AWpWbesWA5bfh6Yn5RJYFreoYCnXzbgA0wadcWh1I8H0vTAQ3Bfez3YnV/AprH2Gwzzzi+A8+eVkYizZ5B+/VUw2O2oWbse8HqR/P+eQt2Md4FkSba6283fa48H5vXrwJYegOkQ/4Bj3r4VjVNeAXw+MZdBQDWJUS0h0u9FK8hIhjujN2w508CWHhCT1Ww500SBHwHN71sAYX1XiTZD3A35sWPHcPToUdx0003xPjVBxAzO68XSLUdRUlaOKrsT6SkWDB2cgZG3DAQjScgK2+Bq/WgHEqrBD9jmGnE7TBoCLsxP59A4egyY0z/CELD2K6DXMc3g9aLx8QnwGY2q/bW1hE7E9+vuVYfd8xXqX5oK27vBw7+cxYKmvzwHb48e8PbsBZgkGeLz56pGE4Ss9cRXXoTp2FEw586iy5g/oGr3/mZhlXt/jZolq5D64D1AQz1/LRx//0TP2+cLyUBqtvoUvPTAB63A6oZxE8J/wBOI5OGQaBPEXdlt/PjxmDJlClavXo3MzEz8/ve/1z3e4+FgMlEdI9G2yFv9HdbuOK7Y/rsb+uOJe37RvMHjAY4rjxPp3z9+5T1OJ3DJJYCaSIvJxM81I4Ovr46UtDSge3fgsHprzqAI80hKAurrAZblPV6B9HSgqIgvh3v4YWDePOB3vwPOnlWO9fDDwD33AKNGAS4XMHAg8M03QGKi/DinE7j0UuDoUe15GQz8OQVefhl46SXgtdeAKVOAESOAzZvV33vRRfw51L4HAwcCBw6IDwW48kqgtJT/nPbubd5+4438HLYHKO4J5xd45RXgoYe0r0Pv+9aWvqtEWMT1U1m9ejV++ctfondv9YYMalRXN7bgjNTpTFKAAF1vuDjdHL7cf0Z135f7z+KuX/WWh9nTLtAerLpJe18MkF2rxwNmIa8PnjJ2NEwnjsGTPQCuW25tllnVMOKerCw4b70diR/O0z0f5/OBkRjxhvET4Rw7DvBwMJ49DbhcSHr9VdS/8BJvpP14e2XBsiC/2ZOv5z1bBOq0V1Wh/qMCgGGQ9O23cE56BhY1Iw7Au2wZ3MdOwOKvvcbRo6j/1xvKELHHA2aBv3e55N7ICPB3uHfeQdUfxyF1UQFYAN7t27UTjg4ebL4PdjtSnnkK9vfmirXdXFUjYHLBljMNSaWl/HtKS1H/yr/EUHnS11/zt8W/DQAyklm4/ecXcC9egprHJmp7zsG+b634XQ1GZ/qdatMSrdu2bcPnn3+OBx98EMuXL8esWbOwc2fonZEIoi1QW+9ElV09+ae6zoHa+jaaGKSSgW06cYxv6BFA45jHZR3R7PMWwbo2uAIaUyNPZDNv99e2+xvAmEoP8F3HSg/IG8H07afIeNfCNmc2LIW84dVblze6XDD7ldAEVBO3JJncatnpqtdZUSFL7hOEWrSwbFoPrlt3dBkzCqaDpbLafZhM2klmtbWyKgPLiuXN858+nbqKEQDibMj/+9//YsWKFVi2bBkeeOABTJw4Eddee208p0AQUdMlyYL0FHWPJy3Zii5JbXgdUa28TEUb3LqsQNYRLfGVF8FUV4V9Oplh0alPDqWfuoDB5wV79Aj//8GODag71zV0YajVAcGT+wQaH58Ae/5C2GbPBHPuHIDgtfvCXFPGjZZVGQhd0uB0Ah9+qHo+6irW+aA6coIIEwvLYOjgDNV9Qwd308xejxSnm8P56kY43dr11aESqsE0NsqXtAI923AQDItmfbJONr2AUMbFl1al6x4brE5d09AxDOzzF4Hrlan7foFQxWnMG9cj+S8TYZv/QfOppLX7tbWaDxBqDwuWFcv59ex16/SFXYhOQ6tlLjz99NOtdWqCiJqRtwwEAJSUVaC6zoG0ZCuGDu4mbo8FIWfGh4qOx8n1yoLPbIbppHqyU2AWu6dXJkxn1fMEPNkDYH//A6Q8+1SzzrfbrRo6bpo4ic+mv+MumObMBpecrKqZbtm0Ho1TXoHt3bfBnjype5l6deriWrXU0AmtYk0mcIOGoLagEKaSvYDHjcR/TwVTFX4kQoq3ew+Y93yl2G6bl4emJ55E6sh7YJ+/SFPvPhC27BAvRPP6q+A6yZoxoQ/1I1ehMyVVAHS9aoRSHx7OcZFQsLkMm/ecVmwfcWUWRo0YHNIYimQ3jRpuaaOPUAhW8+288SZYtm8T+1nbcqYh6T+vKY6rnzwFTU8+LfbG9mQPgH3+QoVRAwCuZy+k3XQNTKdOhjzPQDzZ/VG9fXdzMpheI5v6eqT99nbYc9+DseK8ZCIcjD//DG/XrjBWVsK0owgJK7VLAb0sC2Ng0p4f5/U3wvLFdmXfb6dTs285wNfkmw4dRLldf22+I9GZfqfCTXajWgKCkBCuF2xhGXRPS4j5PJxuDiVl6hnkJWUVuG/4gPAfHLRq1J1OTQlQLqs3HLfejsQPP5BtD7Y2bd75JQBJbfOSRarHCT26hZC7oluYFI9H9NzDhcvMQm3Bcv4BIbDDmFrdNgDbnFl805HNG7TFUBwO2N57R/fcWkYcaA6dK8RhGAb2BUtg1Ih6eHtlIZ3C54QfWiMnCAlLtxzF5j2nUWl3wgeg0u7E5j2nsXSLTo1xCxByZnwY/c01kUqAbiuG+6JL4L7oYlQV7ULtouWwBoTEg+G84koYPLzxEtpqOm+/E4B/rXtbsSgpas9fqKp4prqGzXEwb1wf1lyEpi3O//0duEFD5B3G9JqDhNg4JNqe7MI6uyIJz2QCN+QiWWa/LMt/yIVU002IkCEnCD/BvOBYJJuFSkiZ8f6wcNQZyrLyq3VgD5aCPfg9zOvXgevdB770rmENZ963V/basqoQ5m1b+X3bPof5kzWipKh5/acKQ6iZWc4wsC9YipqlK1GzYAk8WbwehadHT9jfnIGme+9XvsV/b9iirUBAMxa95iAhNQ7RyznI6o3GceNV9zWNHCWbvwBpmhORQoacIPy0pfrwUDLjY94z2uEQu5kBgGXFMthmzwyprlqKISDthi07LGmuchi2/DxxfN2Qu1q9t7Qe/fSP/Oaff4KxvByWrZ9rzklhjPWag4TaOETak93f4tSTPQBVRcWoXbQM5s83qc/lq10wfbtfnL/mHAkiRCg2QxB+BC+4UsWYt0Z9uG5mfKDGdgx0sPnOaM3eMVt2GMb8ubJjPP2y0fjnSYCJBTweJPxnKkyVlWGdh/Efz5YdRsP4ibCPHadxoMYasKqhXQFvYgKMNdWa57WsWC7eJ93OcSHqoguRDFvONJnAjnn9p2h6+lnYFxdCFZcLKY+OUt1FmuZEJJAhJwg/gheslineEvXhwWCMRowaMRj3DR+gyIxXC/1G1Z0qwBsX51AhX2ownTwBY1UVfy6PB57rbxDLpBrHPg5L4TIwdXbxeM5qBaOzji92BwvFcPnLxFSN8JHDaHz0MZiWL0HVms9gXb5EUboliKk0TZyk3RxEp55dYWT916VVVqfZ/Mbj0TbyQPuoARdK9og2ARlygpAQj/rwcFFkxmuEfqPx5AK9cT2kBo3rmgHWL61qWbtKZsQB6BpxIIyHEKFMbOlqTSNsWVIAOB1IfPWfYALC1uLcFy9E0/iJ2p3jPBz4XqsaP42CkfXPx3nLbeG3/Qy1w11bRa9kj2gVyJAThAQ9L7gt4HRzYN96K7Y9o51OzbVqAPBkZsFeUAiYJe05GAZwOJB+09Vg/E1LGI0QO5eUBDAmTaEWzXCy4PU5HM35AHmz1Y2w3Y60/70dAMDuLkbNuk1AUpKiPt55+138A0iUhlSYD3NcPX+gI4fI9Ur2iNaBDDlBqNBS9eGRItS3f/f9Gbyqo7EdkfFgGNjnfoSUPz2G+pdfk3UlAwBvr0x52ZYfW8400YjrYjCoGvHGCRPhGDNOnIOMmhqk/uH3/j7fdwMNvGSsZc1KND31jOIaU+77LQz+em2jy4XEqS/BvnCZohGLeftWNHJcdKVbkogIl5bGe6ZmVnlcewiRh0sL5GYQ0UOGnCDaAUJ9u9HL4ZV7m/tPX3tpT9xxVR/UNbqQnGAGE4nxMJlg3rwBpqNHYCo9EJqX5XDANn+u6q6G8RPhHDUayX9+AnX/nYXU+/5X9TjzxvVoeFFlfdzhQPrwq8GcO8s3DSnZJ+5SjTzU1IAN0IJnd+2ELWdabCMXfmT5CcePw7x+XafxTGOem0HEBCo/I4gYIG1sEssmJ8LYQn2718jgbFqm+PdJuRl/31KB5zaW4+9bKlCw7Ti4EJt5iIQofiLFlpuj2jUN4HXRpbXiXLdusv3u/v15MRihuUfAOrotNwfMOd7TZ4u/VI4fMMeUsX9UtBE1ulywzVZXXIuqO1iopWkdkc587W0c8sgJIgqkkq6VdiesZiMAA5wuLvomJ3706tsdLg4OF//AIKjQAQhZix2IwMtyOGD5WN6b3N2/P+ryC/gQs9OF5Alj+bE//EBh8GVebGDiVICnryZvKpuj3S7KwQZi9HhQtakISEpS7owkciGs1Wt5+U8+3aEzuXWvnbzyVoU8coKIAqmkKwA4XF44XJxM3rVg85GozqGn8qZGWCp0EXhZarKkgnEW1eH8+7W8dllrU4mojZ6nr/Z+eL3gMvm2o56s3sDHH/PKb0tXorZgGbghF4mqddK/sNfIHQ6k3n2XtoBNwQKk3n1XbLzTWMjuxhodFTvqf976kEdOEBHS6HTji2/PBT2uqOQM4PNh1G2DI/LM9erb1RBU6EJJ1gvbywryg9702Hj+QUDCT2m9sPnvObjj+oFgjJJ2K5LWppZVhWh6bLyo+qaF2IYUABgGtnlzmhXeTv8I7N8P9/hJumNEgm1WLtiSvWicMBH2MeMApxMpfx4vtmkVauljUc/fJku7/Cp2evuJ1oM8coKIkIJNR8Swth5eH7C15GxUjVdG3jIQI67MQtcUK4wGID3ZAqtZ/cczZBW6SLwsaYOVgD97wXLY8mYrvPWe1WfhXbsWBafQ7BVn9oZtzixZSD9l7B81S9gELJvWg8vqw3vVHo8imoDFi2PvHUqiFmzRVnBZfWBe/ynfGW39p+Aye4PdtoWfX5RrxjGX3Y0VEj3+mEQ4iJhCd58gIsDp5nDoVFVY74m4/SjU69tXFB2LToUuEi9LT8zE6YRl2WLVXSNKt+Cf3z8E57BMWFgGqXffKZaUCbC7dqq+l+vZE3XT34a3bzZgYsR5qUUTUFoa8zVbRQ5Bbo6YI2BZVQg0NYEtO9y8P9LzU2kXESFkyAkiAmrrnaiucwU/UEJ1nQPl1Y0ws0zEQjPS+vaoVehUjLLTzTUL4ZjCnB/D4OR7C/HW0m/gU9ltr21A+u9/A+9tt8tKygSMHo/stbTOnOubLff6goX4ozWCEjGaQK/flp8nruOzhw7CeOqkbH+kRphKu4hIIUNOEBGg12BFCzPL4O3Cb1Fld8oy2j2cLyIVuViq0Emz7wPnF/K6vskE2y8uhmOXXfW+jClZiYT9+8CdPhXScGzRVvU6c0AWTRDU2xrGT0Tic3+Bvao+ujVbyTq1mtcfmIzHNDXJ5x2JEW4B2V2i88C8/PLLL7f2JPRobAzP64kFiYmWVjlva0HXGz4mxoiKWgeOn7Ur9mVmJKKuUVk25eF8aHLya+pNTg7Hz9rxzZEKbPjqB3yy8xSKS39CRa0DF/dLg9FgULxfby6JNhYmRmlwQ73WJZ8fweY9pxXza3J68Iv++v3InW4OVXYHTCYjLCyjel9YjwtPfzkPOyn9HAAAIABJREFUCfZqGCWGr2H8RNS/8x58DAN27x7Ze5iKCvisVniuuY7f4HA0e+VGI3zpXeFLSETiay+DqaiAoaEezN//hvrEVCCKcj9bbg5sy5fAx7KwLlus21FNC+OZ03A8MjbktWNbbg5sq1fKtimuPwD6d9txSUwM7+Etom+7z6cWOCOIzsXIWwbilisyZUlnVjODIb274Kb/6aWZjCblx/P1qLQ7ZeVq0STFRYJUcCYQvVI2zutFweYyvJi3C5Pf34UX83ahYHMZ7r+pvywxr2uKFc+d24Jup48rxjBv3wouowfMmzaonkNMuvN7yYGJZIHhaEyfHs6lK5GuU69ZCfv8Rc0JfUXF4LJ6675d6EduL1gOqNTAq0KlXUSUaD4uHjx4EP/+979RU1OD+++/H4888oi479FHH8VHH30UlwkSRFuFMRphNBhkmesOF4ct+86id/ekkDLa1YgmKS4S9ARn9ErZhBp6gUBBGjHkb/Khx2+eVR2fPXRQuxGKAMPAlpujbNShEo7G4sXAoxPk4egwWm7KHgwOH+J7iwvn83hQu7xZCEcoOZMi9iN/8mmk3n0natZuCB4ap9IuIko0PfJXXnkFY8aMwdSpU/HVV1/hH//4h7iPPHKC0Pdkz5TXRzxulZ03nvFCT3AmLdmiLGVzOELy4oXEvNS8d5XZ5RKsyxaLJWWqpU2SMjNpeZde1rp0rmqevCrBxHGkJVhZfXSjCLacaWBL9sGWmxP8vFTaRUSJpiFnWRa33HILLr/8crzzzjtwOp2YMWNGPOdGEG0aPU/WG8WzrsXMhFYHHiMEwRk1GhxurCg61qzf7jeM9iq7eO2sR75uKXjxAHTDxlxW7+YwtI7XqZbNHWo4Opy6bD1xHAV69fT5i2BbkM+PmZ9HoXGixdF91Nu9ezeGDRsGAHjjjTfw1FNPYdq0aXCHuvZDEDFAVhLVhnqDR5K5bjQAPh/v6dY2uMCpWHyv14sz5XXIzEiO2/UKJWu7951Cnbf5nA6XVxYuFwxj5oI8pKdcB3tVHV5f9iImP/gveEx8K0+ZIE2QsLGirCwQNS95xTI0jZ8Ie/5CRdg6PT2pOWs9nLrscMvZdOrpbdNeF4VtmIoK2HJz0PT8ZO1rJIgo0fTIX3zxRbz55ptoaGgAAJhMJsyaNQs2mw3fffdd3CZIdF60kqnC7u7VQuh5sloMH5qJf0+4Gs88eDm8Gm67y+PDax/tw7Mzd2DhpsNxuV7GaMR9wzLx6uJ/wORRPqiXlFXAWdcgGsaEtStwZXYX3LNnNS78qQz37l0lHisTpIkybKzqJZcdhi03B8nPTVKE5DF4sDiuqieveQP4B46G8U8C4LPppYp1Ia9Tq7R3Ja+caGk0DfmQIUNQWFiI+++/H3v28GUhRqMRffr0wQUXXBC3CRKdF2lDktbM6tZj5C0D0bu7SnetANKSLBhxZRZGjRiE7mkJ6JJoRmqQ8LnD5cWWvWewdMvRmLdGVYPN/S8GnjksM8oC1XUOsLn/lRnGR79bi1//sAsAcOOhHeiRYMSIK7NCF6QJho6XbJs1Uz9kHm4zGJMJXGZvmLdvA+DPppc8JIRTRqaoM/d75QTRUgT9dr777rt49dVXMWTIEJw7dw4sy2Lp0qXxmBvRiQmWTBXPrG49PJwPjQ79pabUJDNefuwqJCeYxShDSVk5qkNMaNux/6yuUEs0Sw/Ce5OMXiQU8iHwGw/twKor7hVD5QDQ3WpEeuEa2XsT5s9Fst9o9av8EW+5voJrxF/DOr8ugWF5pxMpY0fDdOIYjF7+gUYrZB5Jy82olNUcDsBggG3u++pj572Hpkn/j8RdiBYhaB15//79MWnSJHz22Wc4cuQIJk2ahK5d9QUiCCJaQimJCoWW9mT15ikwdFA3NDk9cLo5RdvTUHC6vYqoRMHmIzhX2YAFGw5FtPQQuGzx5WPPI+MMX+fdr/JHhVc+puxTRTOUQM8zYe2K2IaQPR5Z2Ny8/lOYThwDABj8eTqqIfNI6rIjaOcqfW/qvb8GGhrUe58D/PYACVqCiBVBPfIpU6bg5MmTWLhwIWpqavDss8/itttuw5NPPhmP+RGdFL1EslC6e+lJjoZCqF5usIS3nuk27D9agW0lZ5GWbEajU/2BwuBPgguVopIz2LrvjGybYOQ5zovRd1yo+35pDTjrceHa77fL9gteuZdlccsl3TBspXqplZSY6oMHtvNUqxn3o/DKI6jLjsSDl7137x7Y8vNkdebKiZI3TrQMQT3yAQMG4KOPPkKfPn1w2WWXYfHixaivj7xGliBCQS+RLJTuXuGurwuee6PTHVaCnd48GSPwU1UTqupc8AGoqnNpisSEK82gV95W9M1ZLNionSQXuGxxz57V6Ff5o+wYwSv3ARgxrB/siwtDUjiLlRJZYNmYas24H4VXHm6CXTTKagFKcLr18FQPTrQQQb9ZY8aMkb22WCx4/vnonrinTZuGvXv3wuPxYMKECbj99tujGo/omETa3SvY+rrD1RziDPTcLWZGZmyDebmc1wuvzwer2QiHizecjBHgvPxfqKQnW3DZwK7YVfqzeH6zyQDO6wtrHMDf/3zfGTBGA/7yhysU+6XLASaPGyO+36I6zojSLdh+80PokpoILkNSahWgcKYgWiWywLKxcRM0Da2AWCKG5PDPF4WyGnUsI9oCcX9E3LVrF44cOYKlS5eiuroa9957LxlyQpVIu3sFW1+vtjvFL36gzKiWx1z0zVnAYMCoEYNk3cCWbjmKLXvlIe5wDS8AXNg3DSNvGYSRtwxCeU0T4PNh6zdnFeHzcNh76LzsoUVAuhzgNRrxyr1TNMe4bEh35T3X60keAxTGUZBw9XAwnlX2X/f2yuS93UgfICK9HupYRrQR4m7Ir7rqKlx22WUAgJSUFDQ1NYHjODCkJ0xoIO3BHQrB1tfTUiyoq23S9dwDkXq5o0YMBqDv+ethNTNItJrECAAAFB/4CYd/qJa1Nv32aEWQkfSprnfJHloEhOWAzXtOw2tkcDYtUzY3l5sTox8PxqqULFTUjOOalWh66hnAYgE3RH/tP55Es65OELEk7oacYRgkJPA/yoWFhbjxxht1jXhaWgJMpvgb+YyMCEJ07ZiOdr3XXZ6JtTuU3bauu7wXrGYTrBnJOHmuNmjGeSDfHqvEmN+a0ejwoNHjDvv9AHD7sL4Y/euLMHvFt9iyp3ltWgjjW60smhyesDLbtWCMBmSkKz/bpx4cigSbGbsOnENFTRO6pdpw9aUX4I93DEFtgxtpKRZYza2wpvva24CKccz48H3ghRdCGiIu32WnEyhcororafliJL30Qly88o727zYYne16Q8Xga6UOKJs3b8b777+PefPmITlZ+8MpL6+L46x4MjKSW+W8rUWsrrctSak2Oj1YvKkMh36oRnWdU7a+ntEtGe8sK8G+w+dRVRd+f+PUJDNq6l0wGsLTVLeaGVxzSQ+MuLI3kmwsXp3/taqxtgas0wdiNhlhs5pgb3Ahycqirkm7jv3V8VcjK107mhHsM2upz1R1XKcTaTcOg+mE8gHMk90f1dt3BzWOcfu36/GAOXVCc3dQ6dkYQL9THZdwH1haJY1yx44deO+99zB37lxdI060D/RKvaTrya0xl7RkM66+pCdG3TYICRZe4GTex6WydfFwqannjX84RnzooK7okmTBt8cqsa3kLMwmI5we9cX0YO1PXR4vXP4HCUeQ+vjt+06LSwFqaC1btNRnqjtue2rn2cJ5AgQRDnE35HV1dZg2bRrmz5+P1NTUeJ+eaAGC9aUGYufZBRsncC5VdS7sPPATEqwmjBoxGE43h10HzkV8/khItDJISbRgW8lZcZuWEQ8Hrw/wBhnn8718xv2o2wYHNcDSe7ui6FjQzzQSgn1XyDgSRPjE3ZB/+umnqK6uxjPPPCNue+ONN9CrV694T4WIAcFKve65oT9W7zgetWcXiocYiqxrbb2TzwqPIw0ODjv2nw1+YAvg8wFbS87CYDTg4duGqB6jdm8bNGRno5HHbS+yuwTR3oi7IR85ciRGjhwZ79MSLUSwUq/Fm8rw5YGfxG2RenZanlyjw4PRdwyBhWV051Lll3XtkmRBRqoN56vja8yj6U8eC3Z+9xPuvi4bTU6PIpqhdm+1EORxw6kiEAhFdjekcR0OwGoN+/wE0VGJ7wIm0eEQSr3USE2y4NAP1ar7SsoqQtY/1/Pkdh74CS/MKcaCjYfR5PJozsUAYMNXP8DEGHD1pZ2ve5/DxWHK3N0KtbpwS+hSkyxwebwRadfrfVdCkd0F0KxrTm1BCUKEDDkRFXoSpRf2TYuq8Ykgm1pe3ahb5lVV58LWfWfwSv4ezZCw1x9iXrrlKB777SUYcWUWuqZYYTQAXVOsGHFlFq6/vKfufNo79ka3Qq42lKYvUhqdHrz0wVcR9YaPVnYXaJZu9b71Vou2dCWI9gSJ/xJRoyWles8N2Tj8Q3XYjU84rxcFm8pQcqQCNfUudE2xwMwa4HQHj08LMqlalJRVwM15VRXjOK8Xp87V48fzofcSuCA9AeeqGkM+vi1RUlaO317bT7fpSyBCRn2kSySRyu4CANfYCMfCAiQBaFqwCK8lXYNfXJzZKtURBNGWIENORI2elKqgIBaIlgfGeb14df4emTGNhTCKgFSiVa30qn9mSliG3OnmcPP/ZGLnd+fgdEefiR5PKu1OLN1yFL8c1A2f741MCjbcJDXhu/Lba/vh9Pl6ZHVPQnKCOaT3Hnv+ZVx3urnV6o1bl2J544MAosukJ4j2DhlyImaoGcZwPbCCzUfCMqThIpVoFahrdOH0+Xp8deg8r6keBjX1Ttw8NBP7Dp9vd4Yc4HMMhg/tJWv6Eg7hJr9FWp/urGtA322fybYJrVYp453o7JAhJ1qUcBqfON0cvimLTl88GEMHd4PVbEIdAJfHg399tA9nyusjzio3sww4zovaBm11tSSrCYP7puGbsnLN89xweQ+YGBO+KatAdZDcgVjz7ZHKiIw4EEaSmp9QNAfUYHP/ix7lp2TbhFarK65+MOJMeoLoCNDCEhEXBG9dz2uqrXeiRseIdUk046ahvWBmDBHNwWo24p4b+ouv//XRPvx4PnIjDvBrxtu/PYeuGtnYAODmvNh3uBwmRvufG2syYdSIQfjl4G5IS7LAACBey741DU6kJoUW3g4k1CQ1IHgduWbymtOJ9DXLVHeNKN2CDJsxrIcJguhokEdOtBn0upYBwP8M7gaGMcLFRWZ5HS4+ie6vj1yFukYXzpTHJoT/7dEKDMxKReX3P6vuF0LuLh0Vtv1HKnnxFknbUp+Ok5zZLQHnq5vgjvBeSElPtuKyAenYWqK+rNA1xYpfDuoKn3+e4SapCURcR84wqFtciI93nsROiSaBgGqrVYLoRJAhJ9oM0vaagfTunoT7bhqIlz7YHdU5dh74CfM+LsWQzJSYibRU2p2o/P5nWM0MfD5fRGvlVXZHSMsKBgAXdEvAmYrYZconWE0Yeas/l+FIBWrrXUhP4Y37iCt7Iz3FKhrKB26KXGo3KcEMi8ZavG6I3q9rfkf2ANRsOarIt4h7q1WCaGOQISfaFNLkuKo6B1ITLfjl4G4YNWIQKmsdQWueGSPABbGjxd+dxQ2X9gi7e1kwgjU70aNLkll3WUHAB+BsiEbcamaQnMCistYBM6vdUe3H8/V47cO9aHJ6UFvvQmqSBZcN7IpRIwYpEtDC7Q0vZfWO45pr8aGE6MPJtyCIzgQZcqJNIG3YofVjrRd6NxqAK4d0x5HT1aiu1048A4DyGgc4rw+ZGUktmiEfDr8c1BW7Ss9H9TAQyPWXXYAJ912Og0fO4+3Cb3XHPl3eIP5/db0TW/edAWM0xKzpjd76uNXM4J4bskMeK5qHCYLoiJAhJ1oVvXKkwB9rvdD7Bd0ScfcN2Xgx73zQcxqNfLb5oKwUnK1oANeKQuhGAzD8l71gMBqiNuIG8B5715Tm9Wur2QQzy4Sl3ibAN73JxuodJzTLxUI18Hrr4y43h/pGt9hmliCI8CBDTrQq4ZYjjbxlIA6dqpZ5kABwprwBG77+/+3de3RTZd4v8G/uadqUJqUVys3h7qCVu4KAoPXVd8ZxdJxKZYnO8l3HmTMzHnWtWaMiS3Q8cIQza73DjBccxRnfGZBSdNB517wHRUAZKaDcKn2FAiogtzZt0qZNmjSX80dJSNO9d3bSJLs7+X7+0tDu/TxNm99+nuf3/J4zKCkyJdy+FQoBm3eewN7G/kFfztR8OoXCgNcfxLFvWgd8rTCAcpsZP/3hd1FRao1OiydKIhTT5u7Gxg9P9Ekwi7w/oXAYWo1G9n5wqTYku4WNiPri9jPKqkj9dF9PMOntSJHSrecdXYLf88nhC7L3YO//b+GRu9QWsUzZ23gJrq5AWq7V7OzGC38+iGf+WN9bCz0YkqxxLkUDYG9j/yxxoPc0te2ff4vWDl+/+u1C0lFnnYiEcUROWSE0hT5pdOJDVWKn19/e3iS6RSpZYrPpaqzOJqTN7e8dOUOD6pvHxiQRtsgemUutOIgtA0hVWRtInfV4A12zJ8olDOSUFUJT6HuOXoTZKJxNHT/d6vb4sSvJIG4x6eDx5fcJWTs+P4vDxy9h+qRy3D1/LG78bjk6vQFs2nECF1vTfyZ77ANYfLBNR9Z5qiVeiXIZAzllXLJnXgNXplsjH9yffdmc9FYxjy+Y9i1mSiopMsLT3QN/ILkORUbnOw9+m7b1f5NeC59AgRub1YwiiwEbtzeJBtuBZJ2nWuKVKJfxEZYyTipj2ecP4qZrh/U7Gzwy3Rr54G7v8id9X7vVBIspd55VzUYdepIM4rHSFcTNRh3mXCd8dvu0iUOxdffXSa2fy5VyiVeiHJc7n3I0aEllLNuLzXjg9kkA0G+6NZWRfKzCAgPa3P3vabUYgHAIbq+6PvgvtqV/KjwV8yqHY/Et46HXaQXOoB8rWn1voKeUySnxOjKlKxOpGwM5ZZzU/u/YjOX46VapD24pZqMOc6ZchYZTwlu6Ckx6TB49BJ8cEc7IzmdaLWDU9+YtDCk0wGoxwusLwOn29UlOE1vvbnZ6UqunLgO3sBEJYyCnrEiUsSyUhZzq/udCsx4Lrq8QzXB3uLxYdPcUNJ1px0Xn4BjlDhb/+99m4cMD53G4yQFXpw96nRaV40r71VyPiF/vzmSwlftASJRvGMgpK8RGcMFQSDQxSuqD+5oxJTh22gWhFWOn24f/t/+MaFtMRj3+sKUBbW4/zEYtgsEQuLza6z/rz/YrALPz0HnodFpZyWSZDrbp3MJGlCsYyCmr4kdwibKQ4/c/R7LQL7Z2wSSyda3YYsThE+IniXl9AXgvDxgjh3gMsxXk9Ohcq+2taCeltNiEY6fbBP8tmfXtTAZbHpxC1B8DOSkmURZyJHAsqZqIYDCEnYfOR7eSSR2M4kohw93Z6ZMV7NRKTr/GDLPikMhRqsmsb6cSbGOXVoD+iY/xeHAK0RUM5KQYOVnIkcIiYolr6TLYK7oZ9EAwmN498VoNEA4DJqMOQBgHmxzR1+Klsr4tJ9jGFnhp7fDBbNQC0MDnD7LYC5FM/OsgxUQSo4TEBo5Us9dzSU8AmHVNeVqvGQYwbcJQdPuD0SUGsQeFdCeTRWrub/ywKbrnHOhd6uj2B9O6/5wo13FEToqRmxiVava6kBFDLTjn8Az4Oko429wJnVaT8NhVk0GLQrMBrk4fSoeY4fb0iJTBNeGbix2C19BqegO9PcH6drI1z+NLrGo0Cb9lwPvPiXIdAzkpSk5ilFTAT1aX1w+9VoOACuu2npf5AGK3mvHMQzPR6fFjZEUJXq07jE+P9t8z3+npgV+gzCrQO73+q5qpGDtiCACgtb27T7BOteZ5fHKj0DR+vIHuPyfKdQzkpCg5iVHBUAjhcFj0gJVkpOu40MHsQpsH735yClqNBg2bj6DZ6YXZqEVPINxnNC8WxIHeintjhhfjnY9PRYO1zWrE5DF2LLltQrQMa4ScmuepVupjsRciaQzkNChIJUbV7jiJjw6cy3KL1O2fRy70CdSRNXC5emumf9UnWLe5/dhz9CIOHG8WnRKXmgZPNdeBxV6IpDHZjQY1qVGcTitjgTVPSY22E1k0rQJ3z/+O6M/d1xMSfTCITIMLkUpujLyVZqMOZqNO8AAdIhKW9RH5qlWrcOTIEWg0GixbtgyVlZXZbgKpSIvLK5rkFg6HceOUq3D8tAuuLh/sVjOuHWtDfeNF+HsSJ4RpNMmPVPPBoukj0enpSWn0LDUNLpXrcPO0Ebh91ijZ+8iJ6IqsBvL9+/fj9OnTqK2txalTp7Bs2TLU1tZmswmkMn98v1H032xWMx66YzKA3g/+IosR7+ySt1Wp3GbB2ebOtLQx54TDKe8USDQNLpXcGJskx8Q2IvmyGsjr6+tRVVUFABg3bhza29vR2dmJoqKibDaDsiTZrUnx3B4/zju6RP99bIUVQO9Ir3SIGb/58+eCwVmn1cCg114uMmLGDdcOw76jF5JuTz4wG3Uos1lk7RQwG3WwmPRwdfpkl2HNdInVbn8AzU4PR/OUV7IayB0OB6ZMmRL9f7vdjpaWFslAbrNZoNdn/w+yrMya9XsqKZ39DQZDePPvjdh79AJaXF6UlRTgxmuH4+EfTIFOJz8t4/yJFslKZp8da8HpS/tx47XD0RMIio6w7cUm/PsTC+HpDsBWbIKzw4f/qv8muU7liarZozGyogQA8Mv7psFSYMSH+0/D6+u/W+BfbhiDpd+7Bs4OH2zFJpiNyX2cpPPs8HT9zqkNP6cIUDhrPSxjE6nTmf3iHWVlVrS0uLN+X6Wku78btzf1Gck1O714f/dX8Hj9sk7QirAatdFDUsRErm3Si39Yt7i6ceTLixg7Ygjc7SFYCowYUmiEqzP5muy5pthigNvTA5vVhOmTyvDDuWP6/C786+xRmDbOjm37z+LEt64+55L/YM5ouNu90ANwt3sxkN+ggc7epOt3Tk34OZW7kn1gyWogLy8vh8Nx5VCG5uZmlJWVZbMJlGFyD0KRw2oxYkRZkay1bJ9ElrYGwP/ddBh2qxGFBUb4eoKqCOImgxZjhxfjyzOujN3jf1VXoshsiCaZRQq/6HWafgVfpM4lT1WiwjJyAnw6f+eI1Cirgfymm27CH/7wB9TU1KCxsRHl5eVcH88xcg9CkeuZB6dj5X8cxLmWzpQPDIl8W5vbjza3cAAvLTZh0mgboAljzxeXUrtRGmk1gL8nlNEgbjbqMGJokWDQtpgNfR6gkj2XXC6xY2zD4TA0Go2synHp/p0jUpusBvLp06djypQpqKmpgUajwYoVK7J5e8oCqWznVCp0GfV6PP/wbLS2e9H4dRu2/vNrwdH0QKq+mQxahEIh1B+9CKvFkNI10i0bFWTnXjcMJoOu37R0a4dPNFs9nSNcqZH0p19c7PN+SlWOS/fvHJHaZH2N/Fe/+lW2b0lZJPcgFDl8PUG0dXRj+4Fv0XDSgbYOH0xG4bXwudcNQ9MZF75tEc9yF79PKHqMaYdH/JzzXKHVAAunj8D9t05Iumxqm7sbLS4vRpYNfCZNaiQt9lAm9CCRzt85IjViiVZKOzkHoUiJP6M6VqSAi8mghT8Qgt1qxtQJpQgEQ5Jb1eiKUBjQajTQabVobfckVfglHAZ+t/kwpk8qH/A54ansVRebKo/8bjWcaoXD5U36d45IzRjIKe2S3Sscn9AUv24q/D0hlBQZUTnOjjCAjw/nx75w6+Us84GKjGxTCaZtbn/CA1LkkBpJ67RAUCB/0WjQCU6VR37nfnpvAU5908p95JRXGMgpY6QOQgGEM5Yrx5Wi4VSrrOu7Ov3Yeeg8zCLT7fLaqI1Oqw92o8qLMGl0iehDznC7BRfa5G3XjB3ZigXTogI9TAZdRtfLhWZvKseXYs8X5xOeuy7EbNQzsY3yDgM5KUYoY3nnofNJX2cg9dJnTioXPKtbikEH9AzsNNWkaDXAiLIiPPPgdOi0WoTCYeyJSQYzG3W46bph+OG8q/HrV/fKSvqLTQJbfMt4HD/j6rfNr9MbwOQxdrR2NAteIx0Z4UKzN+2dPuw8KHzanc8fZBY6URwGclKEVJKVRtO7FptpdqsJ9982EUajTjRwCNFoNLiyqS2zrAV6/PxH1+HqYcUwXq5w+MBtk1C9cDxanB5Ao0FZSUF0VDyvcnjCZQmgbxJYIBiGp1t4uv7gceEgDqQ3Izx29mZIkQmlItP99mJmoRPFYyCntJJboUsqYznZIJ7q1rPpk8pgMelx36Lx+PjwOYRkDuz9gewEcQBwewNYveEQSuP2UZsMOowsv1L9KfJzv3v+WABXpqqHXg7yXd4eODt9KCk0YWpcEpjUeyE1u52pjHBmoRMlh4Gc0iJRha54UklWdqsJZpMO5x3y1ntvum4YwkCf6WYh2ssj/TJbASrHlUaDWYvTIzuIK0VsH7XYz/35f5uFTk8Pxl1dCpezCxs/bMKhEw44O31oOOmATquJvjfJJrwNKTRg+uX3NlMGuvOBKJ8wkFNaiFXoAoQzm6VGXYUFhn5TvZGa672JbZroSWaRD/faHScTjsojZ16Pu7oU7nbvlX/QaJLoqbIOHm/pk2Am9nMPhsJY+i+TYDbqUbvjZJ/cg/j3Rs5JZ7Hau3rQcKoVOt3JAW9BE5PpU9KIcgkDOQ1YolrXP5h7Nby+QL8PY6FRl8WsF6ytPu/64fjeDWOi66OxH+6JiprET0ubjXo4Lk9FF5gNeE3izPPBps3tw1+3HcdPvjcZgWBYtN8fHzoHhMP42b3Xy6pDHvtetHV0Q5PgsJpED2rpkmjnAxExkOeUgZ4glSqpNdbWjm489+ZncHX2n26PH3UVmPT4zZ8/E7xO41dO3H/rxGi/Yj/cpe6vAfDYjyuj68nBUAivb/0Cnx45h7YOH7Qi+5UjRpYXotMwxfBGAAATV0lEQVTTI3nIyjBbAZpd3gGXVTUbtej29+6P9/p64OsRvuCnRy+iwKxH1YyRkmvbOw+dh1ank1WHPP692PbZWVkJgDyUhEh5uXtQbx4JhkLYuL0Jy1/fi6df24vlr+/Fxu1NCGZp4TeyxirG2elDGFdGcbU7Tvb598ioy+sLJAw6yd7fXmxGWUzQr91xEu/v/gqtHb1tkgriN0+twIqfzMLzD8+GTSRT2mzUYflPZuHmaSPELyRTtz+Em64dhv/z0zmYf7309f7ZcAFAGCUJMrgbTraI/myEss4j78WSqgmomjkSpcVmyZUHqfeFiLKDgTwHRNZJI8FJLGBmSmSNVa5DTQ74BDZiSwVkqa1OUvePzXL2+AL4Z4P8ferTJgyFTquF1WLEjMnC159XORw6rQZVM0Zi4bQKmI0DG5keu3za2eJbxmPutcNEv67bH8Szb34GZ4Ig2trejQkjSwT/TSoDPBAMo2rGSDz7k5l4/uHZsFuNgl/HQ0mIlMepdZUbLGcxx693FxcaRaejxQqJJNp2BADNTo/g0oGcLOe3P2xKqnhMUcGVPw+h60+dUIpQOIzlr++NZozPvqYM148vw5BCA3Y3XMTHh5MrcBP7s1l6+yR8edoJp1s4WPtlVKQzGfU4fqYNwJWEwdicgXhiWfDTJpbhowP9p9q5HYxIeQzkKjdYzmIWW+9O9mhJoYB5/YRShOMCZvzWtkRZzm6PH43ftMnuj1YLjCi7sk9b6PrvfHwKH8VljH9y5CI+OXIRpcUmTJ0wFCPLCpM6kc1mNUV/NiaDDt8dY0u68lwsry8A7+W3ILKGXzmuVDRBTSwLftH0CowqL4qeCx+pNvfjhWNltUOp/A2ifMBArnKD7Szm2CzjVIp6iAVMuVvb4rOcIyPMz481SyasxRtutwi2MXL9RJnyrR0+fHTgHG6dMQIjyoqw778vybrv5NG2Pve9/7aJONDULHsmwVZkQnuXDzarCV3dPYLf13CqDb6eYL/+SfWp/uilPtv7QmHgbHMntuz6SjJrPdn6AkSUPP4lqZzc9WElLL5lfDRhSqsBSovNqJo5UlZRj9iALLV0ILTWHisywkwmiAO9a9BS15aaCYl1+IQDS6omoFQiGTDCpNfi/tv6BkWLSY95lRWJG4zeQjrPPTwLqx65EY/9uBI+keAvlqCW6vngUj8npfM3iPIBR+Q5YLBWwdJptbj35nFYcH0FEA6jzCY8ypUykKWDRKNmKU63T/DakSniApNeVjW01o7e60wabcOeBFPkN1x7FSym/n+S8e+vRiOcbV9YYIDVYoTVYoSvJ5j0TE06zwcHBk/+BlGuYyDPAYOxCla6plQHsnSQaNRcUmREtz8gOP0cf22h/ljMBllB79/rGuBy+2DSa+ELiE+R3z5rtODrkff3B3Ovxslz7fjj+42CWws93T3RKfNU6pVLfU9kj3s8qfdgsORvEOU6BvIcMpiqYCVbslWMyaBD5fihgsVJhAJSbFLVkCITbFYj2tz9p9WHFBrw/MOz8fc93wgGrsmj+27ZEupPa4cPo8qL4Pb4JafuI1nnUkG8tNgEe7FZsC9FFgO27v4ah5paJB8c4mcRFt8yHpYCIz49cl72TI3Y7E4oHMaOJLPWB1v+BlGuYiCntEvXlGpkFHzkRO+1pLZPic0AFJj1gEAgLy40wWox9gtcRoMOQBifHr2IY2ecmDaxDHfPHyvaH093AM8snYGV/3EArq7k1uFjVY6/EhDj+2KSebpbSZER/kAoOirXabX4H3dfh3+dPUr2TI3Y7E4wFIJWo0lq+YanmBFlBwM5pV26plTjR8FS26ekZgCExE5DRwLXX7Yd77OOHblGp6dHsj/BUBgzrymXfeiIkAXXDxfti9wjWru8AaxYv7/PMgaQ2kxN/PekunwzWPM3iHIJAzmlXTqmVKVG9fHbp1JJahNKZjt+xin4tfu/vASjQQufQAGWSH8W3zIenu5AwoQ2Mb/f8gVmTJIe/ScSmbqPfYh57P4ZKV1LTLIPBYMxf4Mo13D7GaVdOrbEyRnVy/laMfEPFFLXCIUhGMSBK/3RabVYevskWdvMhDjdvcH37Q+bku6LmENNDnT7A2m51kBFHgAYxInSj4GcMmIge8iB5OquJzq0RUj8A4Wca5iNOpQWm0T7k6jmvFbGsefHzjhhE6lrLqSkSPxrne5uONP0UEBEgxen1ikjBjqlmkyilNTXxtNqgDvmXI175l0t+34R/p4glj0wHUaDTrQ/QmvCleNLUTVjJLZ/fhY7D0nXXne6fbhhylWoP5q4ElxJkRHPLJ2BFzccFF3GsBWb4G73JrwWEakXAzll1EC2xCWTKCWUfS6UJHbz1Ar8z3uvR0uLW/Aax047RWuj26zmhEVtpB5gllyu2nawqQXtXT2i9zAa5E2UuTr9CIbCkg88ZqMe/XtKRLmEgZwGrWRG9fFfW2QxYuvur5LKlg4Ew/D6xNeUK8fZZc8qiNV8bzjVio6uHtHiMJXjS9Fw0iHrHloNUGDSMzOcKM8xkNOgl8yoPvZrk53aT5Q0VzVzlPxGx4nfUhYJ4majDv6eYDT4Lpo2ArsEit8ICYV7TzezWozMDCfKYwzklNOSeQiQ2jZXWmzuV3lNLqntcRaTHsuWzkBZSQFMBp1kjfR49pgjT4HBVdmPiLKHWetEl2XqJDmpkb6r0wejXhu9dqLM91jTJ5Vx5E1E2R2RBwIBPPPMMzhz5gyCwSB+/etfY+bMmdlsApEkqfXm2JPPvL6A7CnsZAvkxLehpMiEwgIDPN09cLp9XAMnoj6yGsjfe+89FBQU4O2338aJEyfw9NNPY8uWLdlsApEkoQQ7vU6D2h0ncfB4M9rcfsGa71InuiVbc1wsyS/2QBiOxIkoIquB/K677sKdd94JALDb7XC5XNm8PZFssevNG7c3CdZ8T+ZEt1Qyy+PXvLkGTkRCshrIDQZD9L/feuutaFAnGqzk1HGXc6Iba44TUaZkLJDX1dWhrq6uz2uPPvoo5s+fjw0bNqCxsRHr1q1LeB2bzQK9PvsfeGVl1qzfU0nsr7ALji60uaUzyJ3ubuiMBpQNLZR1zZGyvip9+N7mrnzqK5B//ZUrY4G8uroa1dXV/V6vq6vDjh078Morr/QZoYtxOj2ZaJ6ksjKrYOWvXMX+igv2BGG3Sm8Hs1nNCPp7BuXPkO9t7sqnvgL51d9kH1iyuv3s7Nmz2LRpE1566SWYTKmdEkWUTXK2gw1kaxoR0UBldY28rq4OLpcLjzzySPS19evXw2iUf9oTUbZFEtIOHm9Bm9vXJ2u9clwpFk0b0ed8dCKibNKEw+Gw0o2QosRUSj5N4QDsr1yx+8g7vT3YfuBbNJx0oK3DB7vMrWjZxvc2d+VTX4H86m+yU+ss0UokU+z2r7/v+QY7Y2qiJ7MVLVt8PUFccHQhyNkCopzGQE6UJKktaXK2omVa5KS1Q029SwF26+CcLSCi9OBfNVGSpGqnO93daO9MfOBJJkVOWmvt8CEcvjJbULvjpKLtIqLMYCAnSlKkdroQodrp2ZRotsDXE8xyi4go0xjIiZKUqVPS0mGwzxYQUfpxjZwoBanUTs+GZE9aIyL1YyAnSsFgrZ2e7ElrRKR+DOREAzAYTyQbrLMFRJQZDOREOSZ2tkBnNCDo7+FInCiHMdmNKEeZDDoMH1rIIE6U4xjIiYiIVIyBnIiISMUYyImIiFSMgZyIiEjFGMiJiIhUjIGciIhIxRjIiYiIVIyBnIiISMUYyImIiFSMgZyIiEjFGMiJiIhUjIGciIhIxRjIiYiIVIyBnIiISMUYyImIiFSMgZyIiEjFGMiJiIhUjIGciIhIxRjIiYiIVIyBnIiISMUYyImIiFRMkUDucDgwa9Ys7Nu3T4nbExER5QxFAvmaNWswatQoJW5NRESUU7IeyOvr61FYWIiJEydm+9ZEREQ5J6uB3O/34+WXX8YTTzyRzdsSERHlLH2mLlxXV4e6uro+ry1YsADV1dUoLi6WfR2bzQK9Xpfu5iVUVmbN+j2VxP7mrnzqK5Bf/c2nvgL511+5NOFwOJytm9XU1CAUCgEAzpw5A7vdjrVr12LChAmi39PS4s5W86LKyqyK3Fcp7G/uyqe+AvnV33zqK5Bf/U32gSVjI3IhmzZtiv73U089hXvuuUcyiBMREZE07iMnIiJSsayOyGO9+OKLSt2aiIgoZ3BETkREpGIM5ERERCrGQE5ERKRiDOREREQqxkBORESkYgzkREREKsZATkREpGIM5ERERCrGQE5ERKRiDOREREQqxkBORESkYgzkREREKsZATkREpGIM5ERERCrGQE5ERKRimnA4HFa6EURERJQajsiJiIhUjIGciIhIxRjIiYiIVIyBnIiISMUYyImIiFSMgZyIiEjFGMglOBwOzJo1C/v27VO6KRkVCATw5JNP4v7778d9992Hzz//XOkmZcSqVauwePFi1NTUoKGhQenmZNyaNWuwePFi3Hvvvfjggw+Ubk7GdXd3o6qqCu+++67STcm4999/H3fddRd+9KMfYdeuXUo3J2O6urrwy1/+EkuXLkVNTQ12796tdJMyoqmpCVVVVfjrX/8KALhw4QKWLl2KJUuW4LHHHoPf75f8fgZyCWvWrMGoUaOUbkbGvffeeygoKMDbb7+NlStX4sUXX1S6SWm3f/9+nD59GrW1tVi5ciVWrlypdJMyau/evThx4gRqa2vxxhtvYNWqVUo3KeNeffVVDBkyROlmZJzT6cTLL7+MjRs3Yt26dfjoo4+UblLG/O1vf8N3vvMd/OUvf8HatWtz8u/W4/HghRdewJw5c6Kv/f73v8eSJUuwceNGjBkzBlu2bJG8BgO5iPr6ehQWFmLixIlKNyXj7rrrLjz99NMAALvdDpfLpXCL0q++vh5VVVUAgHHjxqG9vR2dnZ0KtypzZs2ahbVr1wIAiouL4fV6EQwGFW5V5pw6dQonT57EwoULlW5KxtXX12POnDkoKipCeXk5XnjhBaWblDE2my36edTR0QGbzaZwi9LPaDTi9ddfR3l5efS1ffv24dZbbwUALFq0CPX19ZLXYCAX4Pf78fLLL+OJJ55QuilZYTAYYDKZAABvvfUW7rzzToVblH4Oh6PPh4DdbkdLS4uCLcosnU4Hi8UCANiyZQsWLFgAnU6ncKsyZ/Xq1XjqqaeUbkZWfPvtt+ju7sbPfvYzLFmyJOGHvJp9//vfx/nz53HbbbfhgQcewJNPPql0k9JOr9fDbDb3ec3r9cJoNAIASktLE35W6TPWOpWoq6tDXV1dn9cWLFiA6upqFBcXK9SqzBHq76OPPor58+djw4YNaGxsxLp16xRqXfbkS2Xi7du3Y8uWLXjzzTeVbkrGbN26FVOnTs2LZbAIl8uFl156CefPn8eDDz6InTt3QqPRKN2stHvvvfdQUVGB9evX49ixY1i2bFle5EDEkvNZlfeBvLq6GtXV1X1eq6mpQSgUwoYNG3DmzBk0NDRg7dq1mDBhgkKtTB+h/gK9AX7Hjh145ZVXYDAYFGhZZpWXl8PhcET/v7m5GWVlZQq2KPN2796NdevW4Y033oDValW6ORmza9cunD17Frt27cLFixdhNBoxbNgwzJ07V+mmZURpaSmmTZsGvV6P0aNHo7CwEG1tbSgtLVW6aWl38OBBzJs3DwAwefJkNDc3IxgM5vTsEgBYLBZ0d3fDbDbj0qVLfabdhXBqXcCmTZuwefNmbN68GQsXLsSKFStyIoiLOXv2LDZt2oSXXnopOsWea2666SZs27YNANDY2Ijy8nIUFRUp3KrMcbvdWLNmDV577TWUlJQo3ZyM+t3vfod33nkHmzdvRnV1NX7+85/nbBAHgHnz5mHv3r0IhUJwOp3weDw5uXYMAGPGjMGRI0cAAOfOnUNhYWHOB3EAmDt3bvTz6oMPPsD8+fMlvz7vR+TUOxp3uVx45JFHoq+tX78+ukaTC6ZPn44pU6agpqYGGo0GK1asULpJGfWPf/wDTqcTjz/+ePS11atXo6KiQsFWUTpcddVVuP3223HfffcBAJYvXw6tNjfHZIsXL8ayZcvwwAMPIBAI4LnnnlO6SWl39OhRrF69GufOnYNer8e2bdvw29/+Fk899RRqa2tRUVGBu+++W/IaPMaUiIhIxXLzMY6IiChPMJATERGpGAM5ERGRijGQExERqRgDORERkYoxkBORoHfffRdTp07Fnj17lG4KEUlgICeifrZu3YqjR49i8uTJSjeFiBJgICfKc3/605+wfPlyAMBXX32FO+64A7feeiueffbZnCzXS5RrGMiJ8txDDz2Er7/+GgcOHMDzzz+P3/zmNzldm50o1zCQE+U5rVaLVatW4fHHH8fEiRMxe/ZspZtERElgICcitLe3w2Kx4MKFC0o3hYiSxEBOlOd8Ph9WrFiBdevWwWAwYOvWrUo3iYiSwENTiPLcmjVrUFhYiF/84hdwOBxYvHgx7rnnHuzbtw9ffvklKioqMGTIEKxduxZ2u13p5hJRHAZyIiIiFePUOhERkYoxkBMREakYAzkREZGKMZATERGpGAM5ERGRijGQExERqRgDORERkYoxkBMREanY/wf3vEcdEwZ9KAAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(0)\n", + "\n", + "plt.scatter(dist_01[:,0],dist_01[:,1],label='Class 0')\n", + "plt.scatter(dist_02[:,0],dist_02[:,1],color='r',marker='^',label='Class 1')\n", + "plt.xlim(-5,10)\n", + "plt.ylim(-5,10)\n", + "plt.xlabel('x1')\n", + "plt.ylabel('x2')\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(500, 1)\n", + "(500, 1)\n", + "(1000, 3)\n" + ] + } + ], + "source": [ + "y1 = np.zeros((500,1))\n", + "print(y1.shape)\n", + "\n", + "y2 = np.ones((500,1))\n", + "print(y2.shape)\n", + "\n", + "data1 = np.hstack((dist_01,y1))\n", + "data2 = np.hstack((dist_02,y2))\n", + "data = np.vstack((data1,data2))\n", + "\n", + "print(data.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[ 4.61546313 2.66193635 1. ]\n", + " [ 4.14312954 4.21854945 1. ]\n", + " [ 3.5360558 5.44785463 1. ]\n", + " [-0.30283189 1.49333376 0. ]\n", + " [ 3.78745303 6.42600424 1. ]\n", + " [ 1.88347777 4.75120101 1. ]\n", + " [ 4.62331128 4.57041199 1. ]\n", + " [ 3.25889833 6.95708425 1. ]\n", + " [ 0.8891156 -1.34359916 0. ]\n", + " [ 3.17329477 3.51864788 1. ]]\n" + ] + } + ], + "source": [ + "np.random.shuffle(data)\n", + "print(data[:10])" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "split = int(0.8*data.shape[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(800, 2) (200, 2)\n", + "(800,) (200,)\n" + ] + } + ], + "source": [ + "X_train = data[:split,:-1]\n", + "X_test = data[split:,:-1]\n", + "\n", + "Y_train = data[:split,-1]\n", + "Y_test = data[split:,-1]\n", + "\n", + "print(X_train.shape,X_test.shape)\n", + "print(Y_train.shape,Y_test.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "def hypothesis(x,w,b):\n", + " '''accepts input vector x, input weight vector w and bias b'''\n", + " \n", + " h = np.dot(x,w) + b\n", + " return sigmoid(h)\n", + "\n", + "def sigmoid(z):\n", + " return 1.0/(1.0 + np.exp(-1.0*z))\n", + "\n", + "def error(y_true,x,w,b):\n", + " \n", + " m = x.shape[0]\n", + " \n", + " err = 0.0\n", + " \n", + " for i in range(m):\n", + " hx = hypothesis(x[i],w,b) \n", + " err += y_true[i]*np.log2(hx) + (1-y_true[i])*np.log2(1-hx)\n", + " \n", + " \n", + " return -err/m\n", + "\n", + "\n", + "def get_grads(y_true,x,w,b):\n", + " \n", + " grad_w = np.zeros(w.shape)\n", + " grad_b = 0.0\n", + " \n", + " m = x.shape[0]\n", + " \n", + " for i in range(m):\n", + " hx = hypothesis(x[i],w,b)\n", + " \n", + " grad_w += -1*(y_true[i] - hx)*x[i]\n", + " grad_b += -1*(y_true[i]-hx)\n", + " \n", + " \n", + " grad_w /= m\n", + " grad_b /= m\n", + " \n", + " return [grad_w,grad_b] #returning python list\n", + "\n", + "\n", + "# One Iteration of Gradient Descent\n", + "def grad_descent(x,y_true,w,b,learning_rate=0.1):\n", + " \n", + " err = error(y_true,x,w,b)\n", + " [grad_w,grad_b] = get_grads(y_true,x,w,b)\n", + " \n", + " w = w - learning_rate*grad_w\n", + " b = b - learning_rate*grad_b\n", + " \n", + " return err,w,b\n", + " \n", + "def predict(x,w,b):\n", + " \n", + " confidence = hypothesis(x,w,b)\n", + " if confidence<0.5:\n", + " return 0\n", + " else:\n", + " return 1\n", + " \n", + "def accuracy(x_tst,y_tst,w,b):\n", + " \n", + " y_pred = []\n", + " \n", + " for i in range(y_tst.shape[0]):\n", + " p = predict(x_tst[i],w,b)\n", + " y_pred.append(p)\n", + " \n", + " y_pred = np.array(y_pred)\n", + " \n", + " return float((y_pred==y_tst).sum())/y_tst.shape[0]\n", + " \n", + " \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "loss = []\n", + "acc = []\n", + "\n", + "W = 2*np.random.random((X_train.shape[1],))\n", + "b = 5*np.random.random()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "for i in range(300):\n", + " l,W,b = grad_descent(X_train,Y_train,W,b,learning_rate=0.5)\n", + " acc.append(accuracy(X_test,Y_test,W,b))\n", + " loss.append(l)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(loss)\n", + "plt.ylabel(\"negative of log likelihood\")\n", + "plt.xlabel(\"epoch\")\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.98\n" + ] + } + ], + "source": [ + "plt.plot(acc)\n", + "plt.ylabel(\"accuracy\")\n", + "plt.xlabel(\"epoch\")\n", + "plt.show()\n", + "print(acc[-1])" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(0)\n", + "\n", + "plt.scatter(dist_01[:,0],dist_01[:,1],label='Class 0')\n", + "plt.scatter(dist_02[:,0],dist_02[:,1],color='r',marker='^',label='Class 1')\n", + "plt.xlim(-5,10)\n", + "plt.ylim(-5,10)\n", + "plt.xlabel('x1')\n", + "plt.ylabel('x2')\n", + "\n", + "x = np.linspace(-4,8,10)\n", + "y = -(W[0]*x + b)/W[1]\n", + "plt.plot(x,y,color='k')\n", + "\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.76604691 1.49267387]\n", + "-5.424920453033558\n" + ] + } + ], + "source": [ + "print(W)\n", + "print(b)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 1cb465d8b04849675c397b176483dece34ad6915 Mon Sep 17 00:00:00 2001 From: SWARNIMA SHUKLA Date: Fri, 3 Apr 2020 00:13:00 +0530 Subject: [PATCH 22/56] Johnson Algorithm Implementation in Dart (#2567) --- Johnson_Algorithm/Johnson_Algorithm.dart | 180 +++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 Johnson_Algorithm/Johnson_Algorithm.dart diff --git a/Johnson_Algorithm/Johnson_Algorithm.dart b/Johnson_Algorithm/Johnson_Algorithm.dart new file mode 100644 index 0000000000..e1cbc70f97 --- /dev/null +++ b/Johnson_Algorithm/Johnson_Algorithm.dart @@ -0,0 +1,180 @@ +/* +Johnson’s algorithm for All-pairs shortest paths + +Given a weighted Directed Graph where the weights may be negative, +find the shortest path between every pair of vertices in the Graph using +Johnson’s Algorithm. + */ + +int MAX_INT = 9223372036854775807; + +int minDistance(distance, visited) +{ + var minimum = MAX_INT; + var minVertex = 0; + + var v = distance.length; + + for(var vertex = 0; vertex < v; vertex++) + { + if( (minimum > distance[vertex]) && (visited[vertex] == false) ) + { + minimum = distance[vertex]; + minVertex = vertex; + } + } + return minVertex; +} + +void Dijkstra(graph, modified, src) +{ + var num_vertices = graph.length; + var distance = new List(num_vertices); + + var visited = new List(num_vertices); + + for (var i = 0; i < num_vertices; i++) + { + distance[i] = MAX_INT; + visited[i] = false; + } + + distance[src] = 0; + + for(var count = 0; count < num_vertices; count++) + { + var curVertex = minDistance(distance, visited); + visited[curVertex] = true; + for(var vertex = 0; vertex < num_vertices; vertex++) + { + if ((visited[vertex] == false) && (distance[vertex] > (distance[curVertex] + + modified[curVertex][vertex])) && (graph[curVertex][vertex] != 0)) + { + distance[vertex] = (distance[curVertex] + modified[curVertex][vertex]); + } + } + } + + for(var vertex = 0; vertex < num_vertices; vertex++) + { + print('Vertex ${vertex} : ${distance[vertex]}'); + } +} + +List BellmanFord(edges, graph, num_vertices) +{ + var distance = new List(num_vertices+1); + + for(var i = 0; i <= num_vertices; i++) + { + distance[i]=MAX_INT; + } + + distance[num_vertices] = 0; + + for(var i = 0; i < num_vertices; i++) + { + edges.add([num_vertices, i, 0]); + } + + for(var i = 0; i < num_vertices; i++) + { + for(var j in edges) + { + + if((distance[j[0]] != MAX_INT) && (distance[j[0]] + j[2] < distance[j[1]]) ) + { + distance[j[1]] = distance[j[0]] + j[2]; + } + } + } + + return distance; +} + + +void JohnsonAlgorithm(graph) +{ + var edges = new List(); + + for(var i = 0; i < graph.length ; i++) + { + for(var j = 0; j < graph[i].length; j++) + { + if(graph[i][j] != 0) + { + edges.add([i, j, graph[i][j]]); + } + } + } + + var modifiedwei = BellmanFord(edges, graph, graph.length); + + var modified = [[0,0,0,0], + [0,0,0,0], + [0,0,0,0], + [0,0,0,0]]; + + for(var i = 0; i < graph.length; i++) + { + for(var j = 0; j < graph[i].length; j++) + { + if(graph[i][j] != 0) + { + modified[i][j] = (graph[i][j] + + modifiedwei[i] - modifiedwei[j]); + } + } + } + + print ('Modified Graph: ${modified}'); + + for(var src = 0; src < graph.length; src++) + { + print ('\nShortest Distance with vertex ${src} as the source:\n'); + Dijkstra(graph, modified, src); + } +} + +void main() { + + var graph = [[0, -8, 2, 4], + [0, 0, 2, 6], + [0, 0, 0, 2], + [0, 0, 0, 0]]; + + JohnsonAlgorithm(graph); +} + +/* +Modified Graph: [[0, 0, 8, 8], [0, 0, 0, 2], [0, 0, 0, 0], [0, 0, 0, 0]] + +Shortest Distance with vertex 0 as the source: + +Vertex 0 : 0 +Vertex 1 : 0 +Vertex 2 : 0 +Vertex 3 : 0 + +Shortest Distance with vertex 1 as the source: + +Vertex 0 : 9223372036854775807 +Vertex 1 : 0 +Vertex 2 : 0 +Vertex 3 : 0 + +Shortest Distance with vertex 2 as the source: + +Vertex 0 : 9223372036854775807 +Vertex 1 : 9223372036854775807 +Vertex 2 : 0 +Vertex 3 : 0 + +Shortest Distance with vertex 3 as the source: + +Vertex 0 : 9223372036854775807 +Vertex 1 : 9223372036854775807 +Vertex 2 : -9223372036854775801 +Vertex 3 : 0 + + */ From 0ad268e0104bd8b28e0e098a0325e6ebe86ed674 Mon Sep 17 00:00:00 2001 From: Hardev Khandhar <54733460+HardevKhandhar@users.noreply.github.com> Date: Fri, 3 Apr 2020 00:34:45 +0530 Subject: [PATCH 23/56] Boyer Moore Algorithm in C# (#2604) * Boyer Moore Algorithm in C# * Updated Changes --- Boyer_Moore_Algorithm/Boyer_Moore.cs | 110 +++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 Boyer_Moore_Algorithm/Boyer_Moore.cs diff --git a/Boyer_Moore_Algorithm/Boyer_Moore.cs b/Boyer_Moore_Algorithm/Boyer_Moore.cs new file mode 100644 index 0000000000..391afe81aa --- /dev/null +++ b/Boyer_Moore_Algorithm/Boyer_Moore.cs @@ -0,0 +1,110 @@ +// C# Program for Boyer Moore String Matching Algorithm + +using System; + +public class Algorithm +{ + static int CHARACTERS = 256; + + // Getting maximum of two integers + static int max (int a, int b) { return (a > b)? a: b; } + + // Bad Character Pre-Processing Function + static void badChar( char []str, int size,int []badCharacter) + { + int i; + + // Initializing all occurences to -1 + for (i = 0; i < CHARACTERS; i++) + badCharacter[i] = -1; + + // Filling the Actual Value + for (i = 0; i < size; i++) + badCharacter[(int) str[i]] = i; + } + + // Pattern Searching Function + static void search( char []txt, char []pat) + { + int m = pat.Length; + int n = txt.Length; + + int []Character = new int[CHARACTERS]; + badChar(pat, m, Character); + + /* + s is used to keep track of + pattern shifting with respect to text + */ + + int s = 0; + + while(s <= (n - m)) + { + int j = m - 1; + + while(j >= 0 && pat[j] == txt[s+j]) + j--; + + /* + If the pattern is present at current + shift, then index j will become -1 after + the above loop + */ + + if (j < 0) + { + Console.WriteLine("Pattern occurs at index: " + s); + s += (s+m < n)? m-Character[txt[s+m]] : 1; + } + + else + s += max(1, j - Character[txt[s+j]]); + + } + } + + public static void Main() + { + Console.WriteLine("Enter The String Value: "); + String valueEntered = Console.ReadLine(); + Console.WriteLine("Enter The Pattern To Search: "); + String pattern = Console.ReadLine(); + Console.WriteLine(); + + char []txt = valueEntered.ToCharArray(); + char []pat = pattern.ToCharArray(); + search(txt, pat); + } +} + +/** + +Enter The String Value: +ABAAABCD +Enter The Pattern To Search: +ABC + +Pattern occurs at index: 4 + +-------------------------------------------------- + +Enter The String Value: +AABAACAADAABAABA +Enter The Pattern To Search: +AABA + +Pattern occurs at index: 0 +Pattern occurs at index: 9 +Pattern occurs at index: 12 + +-------------------------------------------------- + +Enter The String Value: +THIS IS A TEST TEXT +Enter The Pattern To Search: +TEST + +Pattern occurs at index: 10 + +*/ From 0031422b3e5960b2f60c5e6cbe68680ce9612449 Mon Sep 17 00:00:00 2001 From: Sukriti Shah Date: Fri, 3 Apr 2020 16:38:33 +0530 Subject: [PATCH 24/56] Adding PHP Implementation for Chinese Rem. Th. (#2685) --- .../Chinese_Remainder_Theorem.php | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 Chinese_Remainder_Theorem/Chinese_Remainder_Theorem.php diff --git a/Chinese_Remainder_Theorem/Chinese_Remainder_Theorem.php b/Chinese_Remainder_Theorem/Chinese_Remainder_Theorem.php new file mode 100644 index 0000000000..0275718e99 --- /dev/null +++ b/Chinese_Remainder_Theorem/Chinese_Remainder_Theorem.php @@ -0,0 +1,57 @@ + + From 32f017b11b70a38914c232b42f5cb3f597cfdd5b Mon Sep 17 00:00:00 2001 From: Apoorva <51367534+apoorvam25@users.noreply.github.com> Date: Fri, 3 Apr 2020 22:35:53 +0530 Subject: [PATCH 25/56] Added Minimum Absolute Difference in Array Problem[C and C++] (#1845) --- .../Minimum_Absolute_Difference_In_Array.c | 42 +++++++++++++++++++ .../Minimum_Absolute_Difference_In_Array.cpp | 38 +++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 Minimum_Absolute_Difference_In_Array/Minimum_Absolute_Difference_In_Array.c create mode 100644 Minimum_Absolute_Difference_In_Array/Minimum_Absolute_Difference_In_Array.cpp diff --git a/Minimum_Absolute_Difference_In_Array/Minimum_Absolute_Difference_In_Array.c b/Minimum_Absolute_Difference_In_Array/Minimum_Absolute_Difference_In_Array.c new file mode 100644 index 0000000000..8739a9751d --- /dev/null +++ b/Minimum_Absolute_Difference_In_Array/Minimum_Absolute_Difference_In_Array.c @@ -0,0 +1,42 @@ +/*Given an integer array A of size N, find and return +the minimum absolute difference between any two elements in the array. +The absolute difference between two elements ai, and aj (where i != j ) is |ai - aj|*/ + +#include +#include +#include + +int cmpfunc (const void * a, const void * b) +{ + return (*(int*)a - *(int*)b); +} + +int minAbsoluteDiff(int arr[], int n) +{ + qsort(arr, n, sizeof(int), cmpfunc); + int mindiff = INT_MAX; + for(int i = 0; i < n - 1; i++) + { + if(abs(arr[i] - arr[i + 1]) < mindiff) + mindiff = abs(arr[i] - arr[i + 1]); + } + return mindiff; +} + +int main() +{ + int size, i; + scanf("%d", &size); + int input[size]; + for(i = 0; i < size; i++) + scanf("%d", &input[i]); + + printf("%d", minAbsoluteDiff(input,size)); + return 0; +} + +/* Input : 12 + 922 192 651 200 865 174 798 481 510 863 150 520 + + Output : 2 +*/ diff --git a/Minimum_Absolute_Difference_In_Array/Minimum_Absolute_Difference_In_Array.cpp b/Minimum_Absolute_Difference_In_Array/Minimum_Absolute_Difference_In_Array.cpp new file mode 100644 index 0000000000..ab13f120d6 --- /dev/null +++ b/Minimum_Absolute_Difference_In_Array/Minimum_Absolute_Difference_In_Array.cpp @@ -0,0 +1,38 @@ +/*Given an integer array A of size N,find and return +the minimum absolute difference between any two elements in the array. +The absolute difference between two elements ai, and aj (where i != j ) is |ai - aj|*/ + +#include +#include +#include +using namespace std; + +int minAbsoluteDiff(int arr[], int n) +{ + std::sort(arr, arr + n); + int mindiff = INT_MAX; + for(int i = 0; i < n - 1; i++) + { + if(abs(arr[i] - arr[i + 1] ) < mindiff) + mindiff = abs(arr[i] - arr[i + 1]); + } + return mindiff; +} + +int main() +{ + int size; + cin >> size; + int *input = new int[1 + size]; + + for(int i = 0; i < size; i++) + cin >> input[i]; + cout << minAbsoluteDiff(input, size) << endl; + return 0; +} + +/* Input : 5 + 2 9 0 4 5 + + Output : 1 +*/ From 225ddd013e819d5380b099e03240559c960c8bf0 Mon Sep 17 00:00:00 2001 From: Mansi Agrawal <46123053+mansikagrawal@users.noreply.github.com> Date: Fri, 3 Apr 2020 22:59:12 +0530 Subject: [PATCH 26/56] Count_Inversion.cpp (#2625) --- Count_Inversion/Count_Inversion.cpp | 85 +++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 Count_Inversion/Count_Inversion.cpp diff --git a/Count_Inversion/Count_Inversion.cpp b/Count_Inversion/Count_Inversion.cpp new file mode 100644 index 0000000000..3f4c1601e9 --- /dev/null +++ b/Count_Inversion/Count_Inversion.cpp @@ -0,0 +1,85 @@ +// Count inversion using merge sort + +#include +using namespace std; + +//merge two sorted arrays such that resultant array is also sorted +int merge(int array[], int aux[], int low, int mid, int high) +{ + int x = low, y = mid, z = low, count = 0; + + // checking till left and right half of merge sort + while ((x <= mid-1) && (y <= high)) + { + if (array[x] <= array[y]) + { + aux[z++] = array[x++]; + } + else + { + aux[z++] = array[y++]; + count += mid-x; + } + } + + // Copy remaining elements + while (x <= mid-1) + { + aux[z++] = array[x++]; + } + + while (y <= high) + { + aux[z++] = array[y++]; + } + + // Sorting the original array with the help of aux array + for (int i = low; i <= high; i++) + { + array[i] = aux[i]; + } + return count; +} + +//merge sort to find inversion count +int mergeSort(int array[], int aux[], int low, int high) +{ + int count = 0; + if (high > low) + { + int mid = (low + high) / 2; + + // merge sort on Left half of the array + count = mergeSort(array, aux, low, mid); + // merge sort on Right half of the array + count += mergeSort(array, aux, mid + 1, high); + // Merge the two half + count += merge(array, aux, low, mid + 1, high); + } + return count; +} + +//wrapper function that returns number of inversions +int inversions_count(int array[], int n) +{ + int aux[n]; + return mergeSort(array, aux, 0, n-1); +} + +int main () +{ + int n; + cin >> n; + int arr[n]; + for(int i = 0; i < n; i++) + cin >> arr[i]; + cout << (inversions_count(arr, n)) << endl; + return 0; +} + +/* Sample input +5 +1 20 6 4 5 + +Sample Output +5 */ From ed8d9ecc85bd6450a3c510a621cc172a0718882c Mon Sep 17 00:00:00 2001 From: Aman-Codes <54680709+Aman-Codes@users.noreply.github.com> Date: Sun, 5 Apr 2020 16:38:02 +0530 Subject: [PATCH 27/56] Added Tree Inorder Traversal in JS (#2586) * Create Tree_Inorder_Traversal.js * Update Tree_Inorder_Traversal.js --- .../Tree_Inorder_Traversal.js | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 Tree_Inorder_Traversal/Tree_Inorder_Traversal.js diff --git a/Tree_Inorder_Traversal/Tree_Inorder_Traversal.js b/Tree_Inorder_Traversal/Tree_Inorder_Traversal.js new file mode 100644 index 0000000000..37ea90ebdc --- /dev/null +++ b/Tree_Inorder_Traversal/Tree_Inorder_Traversal.js @@ -0,0 +1,38 @@ +/* + * Program to traverse a tree in Inorder. + */ + +// Creates a Tree Node with input value +class Node { + constructor(value) { + this.value = value; + this.left = null; + this.right = null; + } +} + +// Function for In Order Tree Transversal +function InOrder(root) { + if (root) { + InOrder(root.left); + console.log(root.value); + InOrder(root.right); + } +} + +// Sample Input +var root = new Node(1); +root.left = new Node(2); +root.right = new Node(3); +root.left.left = new Node(4); +root.left.right = new Node(5); +root.right.left = new Node(6); +root.right.right = new Node(7); + +// Sample Output +console.log("In Order traversal of tree is:-"); +InOrder(root); + +/* Output +In Order traversal of tree is:- 4 2 5 1 6 3 7 + */ From fb4cb31a64de01f4dd70fe13c149d3717c8cd67e Mon Sep 17 00:00:00 2001 From: prince-09 <52371330+prince-09@users.noreply.github.com> Date: Sun, 5 Apr 2020 16:45:00 +0530 Subject: [PATCH 28/56] Floyd warshal js (#2468) * floyd Warshall in javascript * floyd warshall in java script * floyd warshall in java script * Update Floyd_Warshall.js * Update Floyd_Warshall.js * Update Floyd_Warshall.js * Update Floyd_Warshall.js * Update Floyd_Warshall.js * Update Floyd_Warshall.js * Update Floyd_Warshall.js * Update Floyd_Warshall.js * Update Floyd_Warshall.js * Update Floyd_Warshall.js --- Floyd_Warshall_Algorithm/Floyd_Warshall.js | 88 ++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 Floyd_Warshall_Algorithm/Floyd_Warshall.js diff --git a/Floyd_Warshall_Algorithm/Floyd_Warshall.js b/Floyd_Warshall_Algorithm/Floyd_Warshall.js new file mode 100644 index 0000000000..5af0847ed0 --- /dev/null +++ b/Floyd_Warshall_Algorithm/Floyd_Warshall.js @@ -0,0 +1,88 @@ +/*The Floyd Warshall Algorithm is for solving the All Pairs Shortest Path problem. +The problem is to find shortest distances between every pair of vertices in a given +edge weighted directed Graph.This is Floyd Warshall algorithm in java script.*/ + +class Graph { + constructor() { + this.edges = {}; + this.nodes = []; + } + + addNode(node) { + this.nodes.push(node); + this.edges[node] = []; + } + + addEdge(node1, node2, weight =1) { + this.edges[node1].push({node:node2, weight:weight }); + this.edges[node2].push({node:node1, weight:weight }); + } + + floydWarshallAlgorithm() { + let dist = {}; + for (let i = 0; i < this.nodes.length; i++) { + dist[this.nodes[i]] = {}; + + // For existing edges assign the dist to be same as weight + this.edges[this.nodes[i]].forEach(e = > (dist[this.nodes[i]][e.node] = e.weight)); + + this.nodes.forEach(n = > { + // For all other nodes assign it to infinity + if (dist[this.nodes[i]][n] == undefined) + dist[this.nodes[i]][n] = Infinity; + // For self edge assign dist to be 0 + if (this.nodes[i] == = n) dist[this.nodes[i]][n] = 0; + }); + } + + this.nodes.forEach(i = > { + this.nodes.forEach(j = > { + this.nodes.forEach(k = > { + // Check if going from i to k then from k to j is better + // than directly going from i to j. If yes then update + // i to j value to the new value + if (dist[i][k] + dist[k][j] < dist[i][j]) + dist[i][j] = dist[i][k] + dist[k][j]; + }); + }); + }); + return dist; + } +} + + let g = new Graph(); + + var edges = prompt("Please enter number of edges", "5"); + + var vertices = prompt("Please enter number of vertices", "5"); + + for(let i=0;i Date: Mon, 6 Apr 2020 03:19:36 +0530 Subject: [PATCH 29/56] Added a Number conversion(Decimal to Binary) code in java (#2524) Number conversion (decimal to binary) --- Number_Conversion/Java/Decimal_to_binary.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Number_Conversion/Java/Decimal_to_binary.java diff --git a/Number_Conversion/Java/Decimal_to_binary.java b/Number_Conversion/Java/Decimal_to_binary.java new file mode 100644 index 0000000000..24a179f0b5 --- /dev/null +++ b/Number_Conversion/Java/Decimal_to_binary.java @@ -0,0 +1,30 @@ +//JAVA program to convert Decimal integer to it's Binary form + +import java.util.Scanner; + +public class Decimal_to_binary { + + //Driver Code + public static void main(String[] args){ + int n, rem; + String Bin = ""; //String to store the binary number + Scanner sc = new Scanner(System.in); + System.out.println("Enter any decimal number:"); + n = sc.nextInt(); //Taking the decimal input + + if (n == 0){ + Bin = "0"; + } + + //Simultaneously storing the remainder when number divided by 2 in the string in reverse order + while (n > 0){ + rem = n % 2; + Bin = rem + Bin; + n = n / 2; + } + System.out.println("Binary number:"+Bin); //output + } +} +//Input : 10 +//Output : 1010 + From ae985519378072dbff5ece529b3cdf7b12fc2715 Mon Sep 17 00:00:00 2001 From: AkanshaKamboj <42874293+AkanshaKamboj@users.noreply.github.com> Date: Mon, 6 Apr 2020 03:21:05 +0530 Subject: [PATCH 30/56] Linked list merge sort in C, C++, Java, Python #1578 (#2395) * Create Linked_List_Merge_Sort.c * Add files via upload * Update Linked_List_Merge_Sort.c * Update Linked_List_Merge_Sort.c * Update Linked_List_MergeSort.cpp * Update Linked_List_MergeSort.java * Update Linked_List_MergeSort.java * Update Linked_List_MergeSort.py * Update Linked_List_MergeSort.cpp * Update Linked_List_MergeSort.java * Update Linked_List_Merge_Sort.c * Rename Linked_List_MergeSort.cpp to Linked_List_Merge_Sort.cpp * Rename Linked_List_MergeSort.py to Linked_List_Merge_Sort.py * Rename Linked_List_MergeSort.java to Linked_List_Merge_Sort.java --- .../Linked_List_Merge_Sort.c | 157 +++++++++++++++++ .../Linked_List_Merge_Sort.cpp | 156 +++++++++++++++++ .../Linked_List_Merge_Sort.java | 165 ++++++++++++++++++ .../Linked_List_Merge_Sort.py | 149 ++++++++++++++++ 4 files changed, 627 insertions(+) create mode 100644 Linked_List_Merge_Sort/Linked_List_Merge_Sort.c create mode 100644 Linked_List_Merge_Sort/Linked_List_Merge_Sort.cpp create mode 100644 Linked_List_Merge_Sort/Linked_List_Merge_Sort.java create mode 100644 Linked_List_Merge_Sort/Linked_List_Merge_Sort.py diff --git a/Linked_List_Merge_Sort/Linked_List_Merge_Sort.c b/Linked_List_Merge_Sort/Linked_List_Merge_Sort.c new file mode 100644 index 0000000000..fa759d2498 --- /dev/null +++ b/Linked_List_Merge_Sort/Linked_List_Merge_Sort.c @@ -0,0 +1,157 @@ +/*C program for sorting a Single Linked List using Merge Sort technique. Merge Sort uses divide and conquer technique i.e. it + divides the input array into two halves, calls itself recursively for the two halves until one element remains and then merges + the two halves + + | 6 | 5 | 4 | 3 | 2 | 1 | * + / \ * + / \ * + | 6 | 5 | 4 | | 3 | 2 | 1 | * + / \ / \ * DIVIDE + / \ / \ * + | 6 | 5 | | 4 | | 3 | 2 | | 1 | * + / \ | / \ | * + |6| |5| | |3| |2| | * + \ / | \ / | + \ / | \ / | + | 5 | 6 | | | 2 | 3 | | * + \ | \ | * + \ | \ | * + | 4 | 5 | 6 | | 1 | 2 | 3 | * MERGE + \ / * + \ / * + | 1 | 2 | 3 | 4 | 5 | 6 | * + */ +#include +#include + +struct Node { + int data; + struct Node* next; +}; + +/*Merging the contents of the two linked list*/ +struct Node *merge(struct Node *l1, struct Node *l2) +{ + if(!l1) + return l2; + + if(!l2) + return l1; + + struct Node *head=NULL; + + if(l1->data < l2->data) + { + head = l1; + l1 = l1->next; + } + else + { + head = l2; + l2 = l2->next; + } + + struct Node *ptr = head; + + while(l1 && l2) + { + if(l1->data < l2->data) + { + ptr->next = l1; + l1 = l1->next; + } + else + { + ptr->next = l2; + l2 = l2->next; + } + ptr = ptr->next; + } + + if(l1) + ptr->next = l1; + else + ptr->next = l2; + + return head; +} + +/*Dividing the linked list*/ +struct Node* mergeSort(struct Node* head) { + + if(head==NULL || head->next==NULL) + return head; + + /*Dividing the linked list into two equal parts as done in merge sort*/ + struct Node *ptr1 = head; + struct Node *ptr2 = head->next; + + while(ptr2 && ptr2->next) + { + ptr1 = ptr1->next; + if(ptr2->next) + ptr2 = ptr2->next->next; + } + + ptr2 = ptr1->next; + ptr1->next = NULL; + + return merge(mergeSort(head),mergeSort(ptr2)); +} + +/* Function for printing the Single Linked List*/ +void printList(struct Node* head) { + + while (head != NULL) { + printf("%d-->", head->data); + head = head->next; + } + + printf("NULL"); +} + +int main() +{ + int test,n,ele; + scanf("%d", &test); + + /* Inserting elements into linked list*/ + while (test--) + { + struct Node* head = NULL; + struct Node *temp = NULL; + scanf("%d", &n); + + while(n--) + { + scanf("%d", &ele); + + struct Node *ptr = (struct Node*)malloc(sizeof(struct Node)); + ptr->data = ele; + ptr->next = NULL; + + if(head==NULL) + head = ptr; + else + temp->next = ptr; + + temp = ptr; + } + + head = mergeSort(head); + printList(head); + } + return 0; +} + +/* +Sample Input +1 - Test cases +5 - Total number of elements to be inserted in linked list +23 2 34 5 1 - Adding the contents of the linked list + +Sample Output +1-->2-->5-->23-->34-->NULL +*/ + + diff --git a/Linked_List_Merge_Sort/Linked_List_Merge_Sort.cpp b/Linked_List_Merge_Sort/Linked_List_Merge_Sort.cpp new file mode 100644 index 0000000000..a5ddf503fe --- /dev/null +++ b/Linked_List_Merge_Sort/Linked_List_Merge_Sort.cpp @@ -0,0 +1,156 @@ +/*C++ program for sorting a Single Linked List using Merge Sort technique. Merge Sort uses divide and conquer technique i.e. it + divides the input array into two halves, calls itself recursively for the two halves until one element remains and then merges + the two halves + | 6 | 5 | 4 | 3 | 2 | 1 | * + / \ * + / \ * + | 6 | 5 | 4 | | 3 | 2 | 1 | * + / \ / \ * DIVIDE + / \ / \ * + | 6 | 5 | | 4 | | 3 | 2 | | 1 | * + / \ | / \ | * + |6| |5| | |3| |2| | * + \ / | \ / | + \ / | \ / | + | 5 | 6 | | | 2 | 3 | | * + \ | \ | * + \ | \ | * + | 4 | 5 | 6 | | 1 | 2 | 3 | * MERGE + \ / * + \ / * + | 1 | 2 | 3 | 4 | 5 | 6 | * + */ + +#include +using namespace std; + +struct Node { + int data; + struct Node* next; + Node(int x) { + data = x; + next = NULL; + } +}; + +/*Merging the contents of the two linked list*/ +struct Node *merge(struct Node *l1, struct Node *l2) +{ + if(!l1) + return l2; + + if(!l2) + return l1; + + struct Node *head = NULL; + + if(l1->data < l2->data) + { + head = l1; + l1 = l1->next; + } + else + { + head = l2; + l2 = l2->next; + } + + struct Node *ptr = head; + + while(l1 && l2) + { + if(l1->data < l2->data) + { + ptr->next = l1; + l1 = l1->next; + } + else + { + ptr->next = l2; + l2 = l2->next; + } + ptr = ptr->next; + } + + if(l1) + ptr->next = l1; + else + ptr->next = l2; + + return head; +} + +/*Dividing the linked list*/ +struct Node* mergeSort(struct Node* head) { + + if(head == NULL || head->next == NULL) + return head; + + /*Dividing the linked list into two equal parts as done in merge sort*/ + struct Node *ptr1 = head; + struct Node *ptr2 = head->next; + + while(ptr2 && ptr2->next) + { + ptr1 = ptr1->next; + if(ptr2->next) + ptr2 = ptr2->next->next; + } + + ptr2 = ptr1->next; + ptr1->next = NULL; + + return merge(mergeSort(head),mergeSort(ptr2)); +} + +void printList(struct Node* head) { + + while (head != NULL) { + printf("%d-->", head->data); + head = head->next; + } + + printf("NULL"); +} + +int main() { + int test,n,ele; + cin >> test; + + while (test--) + { + struct Node *head = NULL; + struct Node *temp = NULL; + cin>>n; + + while(n--) + { + cin>>ele; + + struct Node *ptr = new Node(ele); + + if(head == NULL) + head = ptr; + else + temp->next = ptr; + + temp = ptr; + } + + head = mergeSort(head); + printList(head); + } + return 0; +} + +/* +Sample Input +1 - Test cases +5 - Total number of elements to be inserted in linked list +23 2 34 5 1 - Adding the contents of the linked list + +Sample Output +1-->2-->5-->23-->34-->NULL +*/ + + diff --git a/Linked_List_Merge_Sort/Linked_List_Merge_Sort.java b/Linked_List_Merge_Sort/Linked_List_Merge_Sort.java new file mode 100644 index 0000000000..1021a2c0d4 --- /dev/null +++ b/Linked_List_Merge_Sort/Linked_List_Merge_Sort.java @@ -0,0 +1,165 @@ +/*JAVA program for sorting a Single Linked List using Merge Sort technique. Merge Sort uses divide and conquer technique i.e. + it divides the input array into two halves, calls itself recursively for the two halves until one element remains and then + merges the two halves + + | 6 | 5 | 4 | 3 | 2 | 1 | * + / \ * + / \ * + | 6 | 5 | 4 | | 3 | 2 | 1 | * + / \ / \ * DIVIDE + / \ / \ * + | 6 | 5 | | 4 | | 3 | 2 | | 1 | * + / \ | / \ | * + |6| |5| | |3| |2| | * + \ / | \ / | + \ / | \ / | + | 5 | 6 | | | 2 | 3 | | * + \ | \ | * + \ | \ | * + | 4 | 5 | 6 | | 1 | 2 | 3 | * MERGE + \ / * + \ / * + | 1 | 2 | 3 | 4 | 5 | 6 | * + */ + +import java.util.*; +import java.lang.*; +import java.io.*; + +class Node +{ + int data; + Node next; + Node(int key) + { + data = key; + next = null; + } +} + +class LinkedList +{ + /*Merging the contents of the two linked list*/ + + public static Node merge(Node l1, Node l2) + { + if(l1 == null) + return l2; + + if(l2 == null) + return l1; + + Node head = null; + + if(l1.data < l2.data) + { + head = l1; + l1 = l1.next; + } + else + { + head = l2; + l2 = l2.next; + } + + Node ptr = head; + + while(l1 != null && l2 != null) + { + if(l1.data < l2.data) + { + ptr.next = l1; + l1 = l1.next; + } + else + { + ptr.next = l2; + l2 = l2.next; + } + ptr = ptr.next; + } + + if(l1 != null) + ptr.next = l1; + else + ptr.next = l2; + + return head; + } + + /*Dividing the linked list*/ + public static Node mergeSort(Node head) + { + + if(head == null || head.next == null) + return head; + + Node ptr1 = head; + Node ptr2 = head.next; + + /*Dividing the linked list into two equal parts as done in merge sort*/ + while(ptr2 !=null && ptr2.next != null) + { + ptr1 = ptr1.next; + if(ptr2.next != null) + ptr2 = ptr2.next.next; + } + + ptr2 = ptr1.next; + ptr1.next = null; + + return merge(mergeSort(head),mergeSort(ptr2)); + } + + public static void printList(Node head) + { + if(head == null) + return; + + Node temp = head; + while(temp != null) + { + System.out.print(temp.data + "-->"); + temp = temp.next; + } + System.out.print("NULL"); + } + + public static void main (String[] args) + { + Scanner sc= new Scanner(System.in); + int t = sc.nextInt(); + + LinkedList l = new LinkedList(); + + while(t!=0) + { + int n = sc.nextInt(); + Node head = new Node(sc.nextInt()); + Node temp = head; + + n--; + + while(n!=0){ + temp.next = new Node(sc.nextInt()); + temp = temp.next; + n--; + } + + head = l.mergeSort(head); + l.printList(head); + t--; + } + } +} + +/* + Sample Input + 1 - Test cases + 5 - Total number of elements to be inserted in linked list + 23 2 34 5 1 - Adding the contents of the linked list + + Sample Output + 1-->2-->5-->23-->34-->NULL +*/ + diff --git a/Linked_List_Merge_Sort/Linked_List_Merge_Sort.py b/Linked_List_Merge_Sort/Linked_List_Merge_Sort.py new file mode 100644 index 0000000000..5ed23598f4 --- /dev/null +++ b/Linked_List_Merge_Sort/Linked_List_Merge_Sort.py @@ -0,0 +1,149 @@ +''' + PYTHON program for sorting a Single Linked List using Merge Sort technique. Merge Sort uses divide and conquer technique i.e. + it divides the input array into two halves, calls itself recursively for the two halves until one element remains and then + merges the two halves + + | 6 | 5 | 4 | 3 | 2 | 1 | * + / \ * + / \ * + | 6 | 5 | 4 | | 3 | 2 | 1 | * + / \ / \ * DIVIDE + / \ / \ * + | 6 | 5 | | 4 | | 3 | 2 | | 1 | * + / \ | / \ | * + |6| |5| | |3| |2| | * + \ / | \ / | + \ / | \ / | + | 5 | 6 | | | 2 | 3 | | * + \ | \ | * + \ | \ | * + | 4 | 5 | 6 | | 1 | 2 | 3 | * MERGE + \ / * + \ / * + | 1 | 2 | 3 | 4 | 5 | 6 | * +''' + +import atexit +import io +import sys + +class Node: + + def __init__(self, data): + self.data = data + self.next = None + +# Linked List Class +class LinkedList: + def __init__(self): + self.head = None + + # creates a new node with given value and appends it at the end of the linked list + + def merge(self, l1, l2): + head = None + + # Base cases + if l1 == None: + return l2 + + if l2 == None: + return l1 + + # pick either l1 or l2 and recurse + if l1.data <= l2.data: + head = l1 + l1 = l1.next + else: + head = l2 + l2 = l2.next + + ptr=head + + while l1!=None and l2!=None: + + if l1.data < l2.data: + ptr.next = l1 + l1 = l1.next + else: + ptr.next = l2 + l2 = l2.next + + ptr = ptr.next + + if l1 != None: + ptr.next = l1 + else: + ptr.next = l2 + + return head + + + def mergeSort(self, head): + + if head == None or head.next == None: + return head + + ptr1 = head + ptr2 = head.next + + while(ptr2 != None and ptr2.next != None): + ptr1 = ptr1.next + if ptr2.next != None: + ptr2 = ptr2.next.next + + ptr2 = ptr1.next + ptr1.next = None + + return self.merge(self.mergeSort(head), self.mergeSort(ptr2)) + + +# prints the elements of linked list starting with head +def printList(head): + + if head is None: + return + + temp = head + + while temp: + print(temp.data,end="-->") + temp = temp.next + + print("NULL") + + +if __name__ == '__main__': + t=int(input()) + + for cases in range(t): + n = int(input()) + li = LinkedList() + + temp = li.head + + while n!=0: + ele = int(input()) + ptr = Node(ele) + + if li.head is None: + li.head = ptr + else + temp.next = ptr + + temp = ptr + n -= 1 + + li.head = li.mergeSort(li.head) + printList(li.head) + + ''' + Sample Input + 1 - Test cases + 5 - Total number of elements to be inserted in linked list + 23 2 34 5 1 - Adding the contents of the linked list + + Sample Output + 1-->2-->5-->23-->34-->NULL +''' + From 642f79e5d4a2a742bcb6d98a62866b204a1560c9 Mon Sep 17 00:00:00 2001 From: jedicakelord <46528937+jedicakelord@users.noreply.github.com> Date: Mon, 6 Apr 2020 03:26:55 +0530 Subject: [PATCH 31/56] Chinese Remainder Theorem in Go (#2675) * Chinese Remainder Theorem in Go * Added comments --- .../Chinese_Remainder_Theorem.go | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 Chinese_Remainder_Theorem/Chinese_Remainder_Theorem.go diff --git a/Chinese_Remainder_Theorem/Chinese_Remainder_Theorem.go b/Chinese_Remainder_Theorem/Chinese_Remainder_Theorem.go new file mode 100644 index 0000000000..389734a931 --- /dev/null +++ b/Chinese_Remainder_Theorem/Chinese_Remainder_Theorem.go @@ -0,0 +1,93 @@ +/* Chinese Remainder Theorem : +* Given two arrays number[0..n-1] and remainder[0..n-1] +* Find the minimum possible value of x +* that produces given remainders, i.e +* x % number[0] = remainder[0] +* x % number[1] = remainder[1] and so on. +*/ + +package main + +import "fmt" + +//Extended Euclid Algorithm +func inverse(a int, m int) (x1 int) { + var m0 int = m + x0 := 0 + x1 = 1 + var quotient int + var next int + + if m == 1 { + return 0 + } + + // while the number is greater than 1 + // keep on making (a,m) = (m,a%m) + // Go on reverse to find out x0 and x1 from there. + // where x1 will be the inverse modulo + for a > 1 { + quotient = a / m; next = m + m = a % m + a = next; next = x0 + x0 = x1 - quotient * x0 + x1 = next + } + + if x1 < 0 { + x1 = x1 + m0 + } + + return x1 +} + +func CRT(number []int, rem []int, k int) int { + var prod int = 1 + var prod_exp int + + for i := 0; i < k; i++ { + prod = prod * number[i] + } + + var result int = 0 + + // Optimized CRT formula + for i := 0; i < k; i++ { + prod_exp = prod / number[i] + result = result + rem[i] * inverse(prod_exp, number[i]) * prod_exp + } + + return result % prod +} + +func main() { + var n int + fmt.Println("Enter the size of the array : ") + fmt.Scan(&n) + fmt.Println("Enter the number array : ") + num := make([]int, n) + + for i := 0; i < n; i++ { + fmt.Scan(&num[i]) + } + + fmt.Println("Enter the remainder array : ") + rem := make([]int, n) + + for i := 0; i < n; i++ { + fmt.Scan(&rem[i]) + } + + fmt.Printf("Minimum positive number x is : %d\n", CRT(num, rem, n)) +} + +/* Input : +Enter the size of the array : +3 +Enter the number array : +4 11 9 +Enter the remainder array : +1 2 4 +Output : +Minimum positive number x is : 13 +*/ From 858de8087017bbd84dfef27151b2bda1e7fbacd7 Mon Sep 17 00:00:00 2001 From: HariniJeyaraman <58400069+HariniJeyaraman@users.noreply.github.com> Date: Mon, 6 Apr 2020 21:06:06 +0530 Subject: [PATCH 32/56] 1st commit (#2605) --- Quicksort_3_way/quick_sort_3_way.rb | 71 +++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 Quicksort_3_way/quick_sort_3_way.rb diff --git a/Quicksort_3_way/quick_sort_3_way.rb b/Quicksort_3_way/quick_sort_3_way.rb new file mode 100644 index 0000000000..ce52deb6fa --- /dev/null +++ b/Quicksort_3_way/quick_sort_3_way.rb @@ -0,0 +1,71 @@ +#3 way Quick Sort in Ruby + +def quick_sort(a, lo, hi) + if lo < hi + temp = partition(a, lo, hi) + l = temp[0] + r = temp[1] + quick_sort(a, lo, l - 1) + quick_sort(a, r + 1, hi) + end +end + +def partition(a, lo, hi) + pivot = a[lo] + i = lo + 1 + lt = lo + gt = hi + + while(i <= gt) + + if a[i] < pivot + temp = a[lt] + a[lt] = a[i] + a[i] = temp + lt += 1 + i += 1 + elsif a[i] > pivot + temp = a[i] + a[i] = a[gt] + a[gt] = temp + gt -= 1 + else + i += 1 + end + end + return lt, gt +end + +puts "Enter the size of array : " +n = gets +puts "Enter the values for the array : " +$i = 0 +$num = Integer(n) +arr = Array.new + +while $i < $num do + + arr[$i] = gets + $i +=1 +end +$num2 = Integer(n) - 1 +puts quick_sort(arr, 0, $num2) +puts "After sorting : " +puts arr + +=begin +Sample Input-Output +Enter the size of array : +4 +Enter the values for the array : +10 +14 +12 +13 + +After sorting : +10 +12 +13 +14 +=end From 2612ee89fb4d46c8531520dc4daba581e4180de4 Mon Sep 17 00:00:00 2001 From: SWARNIMA SHUKLA Date: Mon, 6 Apr 2020 22:58:00 +0530 Subject: [PATCH 33/56] Dijkstra Algorithm implementation in dart (#2617) Update Dijkstra_Algorithm.dart --- Dijkstra_Algorithm/Dijkstra_Algorithm.dart | 152 +++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 Dijkstra_Algorithm/Dijkstra_Algorithm.dart diff --git a/Dijkstra_Algorithm/Dijkstra_Algorithm.dart b/Dijkstra_Algorithm/Dijkstra_Algorithm.dart new file mode 100644 index 0000000000..283a735be9 --- /dev/null +++ b/Dijkstra_Algorithm/Dijkstra_Algorithm.dart @@ -0,0 +1,152 @@ +/* + Djikstra's algorithm (named after its discover, E.W. Dijkstra) solves the + problem of finding the shortest path from a point in a graph (the source) + to a destination. + It turns out that one can find the shortest paths from a given source to all + points in a graph in the same time, hence this problem is sometimes called + the single-source shortest paths problem. +*/ +import 'dart:io'; + +var INT_MAX = 9223372036854775807; + +int minDistance(dist, visited, n) +{ + int min = INT_MAX, min_index; + + for (var v = 0; v < n + 1; v++) + { + if (( visited[v] == false ) && ( dist[v] <= min )) + { + min = dist[v]; + min_index = v; + } + } + + return min_index; +} + +void printsol(dist, n) +{ + print('Vertex \t\t Distance from Source\n'); + + for (var i = 0; i < n + 1; i++) + { + print('${i} \t\t ${dist[i]}\n'); + } +} + +void dijkstra(graph, src, n) +{ + var dist = new List(n + 1); + + var visited = new List(n + 1); + + for (var i = 0; i < n + 1; i++) + { + dist[i] = INT_MAX; + visited[i] = false; + } + + dist[src] = 0; + + for (var count = 0; count < n; count++) + { + var u = minDistance(dist, visited, n); + + visited[u] = true; + + for (var v = 0; v < n + 1; v++) + { + if ( !visited[v] && graph[u][v] > 0 && dist[u] != INT_MAX + && dist[u] + graph[u][v] < dist[v] ) + { + dist[v] = dist[u] + graph[u][v]; + } + } + } + + printsol(dist, n); +} + +void main() +{ + print('Enter number of nodes 0 to ?'); + + int n = int.parse(stdin.readLineSync()); + + var max_edges = (n + 1) * (n); + + var adjmat = new List.generate(n + 1, (_) => new List(n + 1)); + + for(var i = 0; i <= n; i++) + { + for(var j = 0; j <= n; j++) + { + adjmat[i][j] = 0; + } + } + + print('Enter in the following format\nsrc\ndest\nweight\n'); + for(var i = 0; i < max_edges; i++) + { + var src = int.parse(stdin.readLineSync()); + var dest = int.parse(stdin.readLineSync()); + var weight = int.parse(stdin.readLineSync()); + + print('*' * 20); + + if( (src == -1) && (dest == -1) ) + { + break; + } + + if( src > n || dest > n || src < 0 || dest < 0 ) + { + print('Invalid edge!\n'); + i--; + } + else + { + adjmat[src][dest] = weight; + } + } + + dijkstra(adjmat, 0, n); +} + +/* +Input: +Enter number of nodes 0 to ? +9 +Enter in the following format +Source +Destination +Weight +******************************************************* +The adjacency matrix will look like this +admat=[[0, 14, 0, 7, 0, 0, 0, 8, 0, 10], + [14, 0, 8, 0, 0, 0, 0, 11, 0, 0], + [0, 8, 0, 7, 0, 4, 0, 0, 2, 0], + [7, 0, 7, 0, 9, 12, 0, 0, 0, 5], + [0, 0, 0, 9, 0, 0, 0, 0, 0, 0], + [0, 0, 4, 0, 0, 0, 2, 0, 0, 11], + [0, 0, 0, 12, 0, 2, 0, 1, 6, 15], + [8, 11, 0, 0, 0, 0, 1, 0, 7, 0], + [0, 0, 2, 0, 0, 0, 6, 7, 0, 0], + [10, 0, 0, 5, 0, 11, 15, 0, 0, 0]]; +******************************************************* +Output: +Distance from Source: +Vertex Distance +0 0 +1 14 +2 14 +3 7 +4 16 +5 11 +6 9 +7 8 +8 15 +9 10 +*/ From 4a5a5e4e5dfeb4f76bdc71662a36d7fceb3d53c7 Mon Sep 17 00:00:00 2001 From: Lakshyajit Laxmikant <30868587+lakshyajit165@users.noreply.github.com> Date: Mon, 6 Apr 2020 23:02:10 +0530 Subject: [PATCH 34/56] added selection sort logic in typescript (#2693) --- Selection_Sort/Selection_Sort.ts | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 Selection_Sort/Selection_Sort.ts diff --git a/Selection_Sort/Selection_Sort.ts b/Selection_Sort/Selection_Sort.ts new file mode 100644 index 0000000000..1c77907e84 --- /dev/null +++ b/Selection_Sort/Selection_Sort.ts @@ -0,0 +1,35 @@ +// function for selection sort logic +function Selection_Sort(numbers: number[]) : number[]{ + + let i: number; + let j: number; + let min: number; + let temp: number; + + // outer loop to traverse through each element + for(i = 0; i < numbers.length - 1; i++){ + min = i; + + // inner loop finds the minimum element and puts it in the beginning. + for(j = i + 1; j < numbers.length; j++){ + if(numbers[j] < numbers[min]){ + min = j; + } + } // inner loop ends + + if(i !== min){ + temp = numbers[i]; + numbers[i] = numbers[min]; + numbers[min] = temp; + } + } // outer loop ends + + return numbers; +} + +const numbers: number[] = [10, 9, 8, 1, 5, 2, 4, 7, 3]; + +console.log(Selection_Sort(numbers)); + +// INPUT [10, 9, 8, 1, 5, 2, 4, 7, 3] +// OUTPUT [ 1, 2, 3, 4, 5, 7, 8, 9, 10 ] From abb028edcee368661f6c2f47eff9a93001e76141 Mon Sep 17 00:00:00 2001 From: Hardev Khandhar <54733460+HardevKhandhar@users.noreply.github.com> Date: Tue, 7 Apr 2020 11:16:36 +0530 Subject: [PATCH 35/56] Tower Of Hanoi In Ruby (#2701) --- Tower_Of_Hanoi/Tower_Of_Hanoi.rb | 37 ++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 Tower_Of_Hanoi/Tower_Of_Hanoi.rb diff --git a/Tower_Of_Hanoi/Tower_Of_Hanoi.rb b/Tower_Of_Hanoi/Tower_Of_Hanoi.rb new file mode 100644 index 0000000000..1165b804c5 --- /dev/null +++ b/Tower_Of_Hanoi/Tower_Of_Hanoi.rb @@ -0,0 +1,37 @@ +## Tower Of Hanoi In Ruby + +## Recursive Function +def tower(disk, source, auxilary, destination) + if disk == 1 + puts "Disk #{disk} moves from #{source} to #{destination}" + return + end + + tower(disk - 1, source, destination, auxilary) + puts "Disk #{disk} moves from #{source} to #{destination}" + tower(disk - 1, auxilary, source, destination) + nil + +end + +## Taking User Input For Number Of disks +puts "Enter the number of disks: " +disk = gets.to_i +puts + +## Fucntion Call +tower(disk, 'source', 'auxiliary', 'destination') + +=begin + +Enter the number of disks: 3 + +Disk 1 moves from Source to Destination +Disk 2 moves from Source to Auxiliary +Disk 1 moves from Destination to Auxiliary +Disk 3 moves from Source to Destination +Disk 1 moves from Auxiliary to Source +Disk 2 moves from Auxiliary to Destination +Disk 1 moves from Source to Destination + +=end From 4a85c0ee43d37c76a162bfdfa4fd3009521f3ed8 Mon Sep 17 00:00:00 2001 From: sandhyabhan <52604131+sandhyabhan@users.noreply.github.com> Date: Thu, 9 Apr 2020 15:08:15 +0530 Subject: [PATCH 36/56] Add Inorder Traversal in Kotlin (#2657) Updated inorder --- Tree_Inorder_Traversal/Inorder_Traversal.kt | 62 +++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 Tree_Inorder_Traversal/Inorder_Traversal.kt diff --git a/Tree_Inorder_Traversal/Inorder_Traversal.kt b/Tree_Inorder_Traversal/Inorder_Traversal.kt new file mode 100644 index 0000000000..5acd29580a --- /dev/null +++ b/Tree_Inorder_Traversal/Inorder_Traversal.kt @@ -0,0 +1,62 @@ +//Code for printing inorder traversal in kotlin + +class Node +{ + //Structure of Binary tree node + int num; + Node left, right; + public node(int num) + { + key = item; + left = right = null; + } +} + +class BinaryTree +{ + Node root; + BinaryTree() + { + root = null; + } + //function to print inorder traversal + fun printInorder(Node: node):void + { + if (node == null) + return; + printInorder(node.left); + //printing val of node + println(node.num); + printInorder(node.right); + } + + fun printInorder():void + { + printInorder(root); + } +} + + //Main function +fun main() +{ + BinaryTree tree = new BinaryTree(); + var read = Scanner(System.`in`) + println("Enter the size of Array:") + val arrSize = read.nextLine().toInt() + var arr = IntArray(arrSize) + println("Enter data of binary tree") + + for(i in 0 until arrSize) + { + arr[i] = read.nextLine().toInt() + tree.root = new Node(arr[i]); + } + + println("Inorder traversal of binary tree is"); + tree.printInorder();//function call +} + +/* +Input: 10 8 3 30 5 19 4 5 1 +Output:5 3 1 2 8 10 19 30 4 +*/ From 095d276c0d392f559b3534d8f1b67d397152e215 Mon Sep 17 00:00:00 2001 From: reeha <56428237+syedareehaquasar@users.noreply.github.com> Date: Thu, 9 Apr 2020 19:39:59 +0530 Subject: [PATCH 37/56] README FOR FORD FULKERSON METHOD (#2589) --- Ford_Fulkerson_Method/README.md | 70 +++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 Ford_Fulkerson_Method/README.md diff --git a/Ford_Fulkerson_Method/README.md b/Ford_Fulkerson_Method/README.md new file mode 100644 index 0000000000..74c1fddd7f --- /dev/null +++ b/Ford_Fulkerson_Method/README.md @@ -0,0 +1,70 @@ +# Ford-Fulkerson Algorithm + +The Ford-Fulkerson algorithm is an algorithm that tackles the max-flow min-cut problem. That is, given a network with vertices and edges between those vertices that have certain weights, how much "flow" can the network process at a time? Flow can mean anything, but typically it means data through a computer network. + +It was discovered in 1956 by Ford and Fulkerson. This algorithm is sometimes referred to as a method because parts of its protocol are not fully specified and can vary from implementation to implementation. An algorithm typically refers to a specific protocol for solving a problem, whereas a method is a more general approach to a problem. + +The Ford-Fulkerson algorithm assumes that the input will be a graph, GG, along with a source vertex, ss, and a sink vertex, tt. The graph is any representation of a weighted graph where vertices are connected by edges of specified weights. There must also be a source vertex and sink vertex to understand the beginning and end of the flow network. + +Ford-Fulkerson has a complexity of O\big(|E| \cdot f^{*}\big),O(∣E∣⋅f +∗ + ), where f^{*}f +∗ + is the maximum flow of the network. The Ford-Fulkerson algorithm was eventually improved upon by the Edmonds-Karp algorithm, which does the same thing in O\big(V^2 \cdot E\big)O(V +2 + ⋅E) time, independent of the maximum flow value. + +## ALGORITHM +Follow 3 basic steps: +1. Find augmented path +2. Complete the bottle neck capacity +3. Augment each edge and total flow +Repeat these steps until the augmented path is reached + +### Example: +![step1](https://github.com/syedareehaquasar/hello-world/blob/master/e.PNG) +here only 2 spaces are there in DT so taking 2 +![step2](https://github.com/syedareehaquasar/hello-world/blob/master/ee.PNG) +Similarly another path +![step3](https://github.com/syedareehaquasar/hello-world/blob/master/eee.PNG) +Similarly another path +![step5](https://github.com/syedareehaquasar/hello-world/blob/master/eeeee.PNG) +Similarly another path +![step6](https://github.com/syedareehaquasar/hello-world/blob/master/eeeeeeeeeee.PNG) +Here paths SA and CD are full but we require 2 in AC but place of only 1 in CD so we have reached our answer ->19 +![final answer](https://github.com/syedareehaquasar/hello-world/blob/master/eeeeeeeeeeeeeee.PNG) + +## PSEUDOCODE + +The pseudo-code for this method is quite short; however, there are some functions that bear further discussion. The simple pseudo-code is below. +This pseudo-code is not written in any specific computer language. Instead, it is an informal, high-level description of the algorithm. + +Ford-Fulkerson Algorithm ((Graph GG, source ss, sink t):t): +``` +initialize flow to 0 +path = findAugmentingPath(G, s, t) +while path exists: + augment flow along path #This is purposefully ambiguous for now + G_f = createResidualGraph() + path = findAugmentingPath(G_f, s, t) +return flow +``` + +# Time Complexity +O(max_flow * E) +Time complexity of the above algorithm is O(max_flow * E). We run a loop while there is an augmenting path. In worst case, we may add 1 unit flow in every iteration. Therefore the time complexity becomes O(max_flow * E) +![tc](https://github.com/syedareehaquasar/hello-world/blob/master/h.PNG) + +# Implementation + + - [c code](https://github.com/jainaman224/Algo_Ds_Notes/blob/master/Ford_Fulkerson_Method/Ford_Fulkerson_Method.c) + - [coffee code] + - [cpp code](https://github.com/jainaman224/Algo_Ds_Notes/blob/master/Ford_Fulkerson_Method/Ford-Fulkerson.cpp) + - [c# code] + - [go code] + - [java code](https://github.com/jainaman224/Algo_Ds_Notes/blob/master/Ford_Fulkerson_Method/Ford_Fulkerson_Method.java) + - [javaScript code] + - [kotlin code] + - [python code](https://github.com/jainaman224/Algo_Ds_Notes/blob/master/Ford_Fulkerson_Method/Ford_Fulkerson_Method.py) + - [ruby code] + - [dart code] From eb3b7459fbb65a62d18ca6e55cc555c70e7e3ac7 Mon Sep 17 00:00:00 2001 From: kushagra-anand <52084821+kushagra-anand@users.noreply.github.com> Date: Fri, 10 Apr 2020 15:02:42 +0530 Subject: [PATCH 38/56] Kadane Algorithm (#2534) * Create Kadane Algorithm in GO --- Kadane_Algorithm/Kadane_Algorithm.go | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 Kadane_Algorithm/Kadane_Algorithm.go diff --git a/Kadane_Algorithm/Kadane_Algorithm.go b/Kadane_Algorithm/Kadane_Algorithm.go new file mode 100644 index 0000000000..d9bf096461 --- /dev/null +++ b/Kadane_Algorithm/Kadane_Algorithm.go @@ -0,0 +1,55 @@ +// Go program to print largest contiguous array sum + +package main + +import "fmt" + +func KAlgo(a []int, n int) int { + var max int + var check_max int + max = 0 + check_max = 0 + + for i := 0; i < n; i++ { + check_max = check_max + a[i] + + // Minimum sum will be 0 + if check_max < 0 { + check_max = 0 + } + if max < check_max { + max = check_max + } + } + return max +} + +//Main Function +func main() { + var n int + fmt.Print("Enter number of Elements ") + fmt.Scan(&n) + ope(n) +} + +func ope(n int) { + fmt.Print("\nEnter Elements ") + a := make([]int, n) + + // Array input + for i := 0; i < n; i++ { + fmt.Scan(&a[i]) + } + + var output int + + // Function Calling for the Algo + output = KAlgo(a, n) + fmt.Println("\nSum of the sub array: ", output) +} + +/* +Enter Number of Elements 6 +Enter Elements 2 -4 -5 -6 8 10 +Sum of the sub array: 18 +*/ From 959b2cdfa4d649ee5de03c3c133eb7b118445fad Mon Sep 17 00:00:00 2001 From: Ravi Kanth Gojur Date: Fri, 10 Apr 2020 22:01:49 +0530 Subject: [PATCH 39/56] Boyer Moore Algo in c added (#2644) --- Boyer_Moore_Algorithm/Boyer_Moore.c | 63 +++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Boyer_Moore_Algorithm/Boyer_Moore.c diff --git a/Boyer_Moore_Algorithm/Boyer_Moore.c b/Boyer_Moore_Algorithm/Boyer_Moore.c new file mode 100644 index 0000000000..ec88ef89d4 --- /dev/null +++ b/Boyer_Moore_Algorithm/Boyer_Moore.c @@ -0,0 +1,63 @@ +#include +#define MAX 256 + +int findmax(int a, int b) +{ + return (a > b) ? a : b; +} + +void searchwrongchar(char *str, int size, int extra[MAX]) +{ + for (int i = 0; i < MAX; ++i) + extra[i] = -1; + + for (int i = 0; i < size; ++i) + extra[(int)str[i]] = i; +} + +void search(char *text, char *pattern) +{ + int patLen = strlen(pattern); + int txtLen = strlen(text); + + int extra[MAX]; + + searchwrongchar(pattern, patLen, extra); + + int s = 0; + while (s <= (txtLen - patLen)) + { + int j = patLen - 1; + + while (j >= 0 && pattern[j] == text[s + j]) + j--; + + if (j < 0) + { + printf("\n\nPattern Matches at shift of = %d.", s); + s += (s + patLen < txtLen) ? patLen - extra[text[s + patLen]] : 1; + } + else + s += findmax(1, j - extra[text[s + j]]); + } +} + +int main() +{ + char text[MAX], pattern[MAX]; + printf("Enter the Text: "); + scanf("%s", &text); + printf("\nEnter the Pattern to Match: "); + scanf("%s", &pattern); + search(text, pattern); + return 0; +} + +/* +INPUT: +Enter the Text: ABAAABCD +Enter the Pattern to Match: ABC + +OUTPUT: +Pattern match at shift = 4 +*/ From e50a7acab2866bf995f90679f60d42494164c671 Mon Sep 17 00:00:00 2001 From: jedicakelord <46528937+jedicakelord@users.noreply.github.com> Date: Fri, 10 Apr 2020 23:10:12 +0530 Subject: [PATCH 40/56] Boyer Moore in Go (#2687) --- Boyer_Moore_Algorithm/Boyer_Moore.go | 78 ++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 Boyer_Moore_Algorithm/Boyer_Moore.go diff --git a/Boyer_Moore_Algorithm/Boyer_Moore.go b/Boyer_Moore_Algorithm/Boyer_Moore.go new file mode 100644 index 0000000000..0927661940 --- /dev/null +++ b/Boyer_Moore_Algorithm/Boyer_Moore.go @@ -0,0 +1,78 @@ +/*Boyer Moore Algorithm for Pattern Search*/ +package main + +import "fmt" + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +//Using Bad Character Heuristic method +func preprocess(str string, length int, chars []int) { + + for i,_:=range(chars) {chars[i] = 1} + + //The last occurrence of the char + for k := 0; k < length; k++ { + chars[int(str[k])] = k; + } +} + +func boyreMoore(text string, pattern string) { + var lenStr int = len(text) + var lenPattern int = len(pattern) + + chars := make([]int, 128) + + preprocess(pattern, lenPattern, chars) + + //shift of the pattern with respect to text + var shift int = 0 + + for shift <= lenStr - lenPattern { + match := lenPattern - 1 + + for (match >= 0 && pattern[match] == text[shift + match]) { + match = match - 1 + } + + // If pattern found, match = -1 + if match < 0 { + fmt.Printf("Pattern found at : %d\n", shift) + + // Shift the pattern so that the next character in text + //aligns with the last occurrence of it in pattern. + if shift + lenPattern < lenStr { + shift = shift + lenPattern - chars[text[shift + lenPattern]] + } else { + shift = 1 + } + } else { + shift = shift + max(1, match - chars[text[shift + match]]); + } + } +} + +func main() { + var text string + var pattern string + fmt.Println("Enter the text : ") + fmt.Scan(&text) + fmt.Println("Enter the pattern to search : ") + fmt.Scan(&pattern) + + boyreMoore(text, pattern) + +} + +/*Input : +* Enter the text : +* therethenthat +* Enter the pattern : +* the +* Pattern found at : 0 +* Pattern found at : 8 +*/ From 3f702f50ea4ee855ef21b9d2d90f8129a9a59976 Mon Sep 17 00:00:00 2001 From: coderprasukj <60914425+coderprasukj@users.noreply.github.com> Date: Sun, 12 Apr 2020 20:30:20 +0530 Subject: [PATCH 41/56] Kruskal Algo in C (#2255) --- Kruskal_Algorithm/Kruskal_Algorithm.c | 153 ++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 Kruskal_Algorithm/Kruskal_Algorithm.c diff --git a/Kruskal_Algorithm/Kruskal_Algorithm.c b/Kruskal_Algorithm/Kruskal_Algorithm.c new file mode 100644 index 0000000000..4f76922964 --- /dev/null +++ b/Kruskal_Algorithm/Kruskal_Algorithm.c @@ -0,0 +1,153 @@ +// Kruskal Algorithm in C +#include +#define NUM 20 + +// Creating the edge +typedef struct edge +{ + int p; // Variable to contain all the first node of the edge + int q; // Variable to contain all the second node of the edge + int weight; // Variable to contain the weight of the edge +} edge; + +// Creating the Edgelist +typedef struct edgelist +{ + edge data[NUM]; + int n; +} edgelist; + +edgelist list; +int weights[NUM][NUM]; // Array for weights in the graph +int n; +edgelist listSpan; + +void kruskal_algo(); +void print(); +int find(int contain[], int vertexno); +void union1(int contain[], int c1, int c2); +void sort(); + +// Driver Program +int main() +{ + int total_cost; + printf("\nEnter number of vertices : "); + scanf("%d", &n); // Number of Vertices + + printf("\nEnter the adjacency matrix : \n"); + + for(int i = 0; i < n; i++) // Enter the Adjacency Matrix + for(int j = 0; j < n; j++) + scanf("%d", &weights[i][j]); + + kruskal_algo(); + print(); + return 0; +} + +// Function performing Kruskal's algorithm +void kruskal_algo() +{ + int contain[NUM], x, y; + list.n = 0; + + for(int i = 1; i < n; i++) + for(int j = 0; j < i; j++) + { + if(weights[i][j] != 0) + { + // Containing all the first node of the edges + list.data[list.n].p = i; + // Containing all the second node of the edges + list.data[list.n].q = j; + // Containing the weight of the edges + list.data[list.n].weight = weights[i][j]; + list.n++; + } + } + + // Sorting the edges according to their weight. + sort(); + + for(int i = 0; i < n; i++) + contain[i] = i; // Intializing the array with first node + + listSpan.n = 0; + + for(int i = 0; i < list.n; i++) + { + x = find(contain, list.data[i].p); // x is the first node of the edge + y = find(contain, list.data[i].q); // y is the second node of the edge + if(x != y) + { + listSpan.data[listSpan.n] = list.data[i]; + listSpan.n = listSpan.n+1; + union1(contain, x, y); + } + } +} + +// Returns the value present at k[vertex_number] +int find(int contain[], int vertex_number) +{ + return(contain[vertex_number]); +} + +void union1(int contain[], int c1, int c2) +{ + for(int i = 0; i < n; i++) + if(contain[i] == c2) + contain[i] = c1; +} + +// Sorting all the edges in increasing order +// according to their weight. +void sort() +{ + edge temp; + for(int i = 1; i < list.n; i++) + { + for(int j = 0; j < list.n-1; j++) + { + if(list.data[j].weight > list.data[j+1].weight) + { + temp = list.data[j]; + list.data[j] = list.data[j+1]; + list.data[j+1] = temp; + } + } + } +} + +// Printing the Output +void print() +{ + int cost = 0; + for(int i = 0; i < listSpan.n; i++) + { + printf("\n%d\t%d\t%d", listSpan.data[i].p, listSpan.data[i].q, listSpan.data[i].weight); + cost = cost + listSpan.data[i].weight; + } + printf("\nCost of the spanning tree = %d\n", cost); +} + +/* +INPUT : +Enter number of vertices : 6 +Enter the Adjacency Matrix : + 0 3 0 0 6 5 + 3 0 1 0 0 4 + 0 1 0 6 0 4 + 0 0 6 0 8 5 + 6 0 0 8 0 2 + 5 4 4 5 2 0 + +OUTPUT : + + 2 1 1 + 5 4 2 + 1 0 3 + 5 1 4 +Cost of the spanning tree = 15 +*/ From 7f6c275219f2be84c547b4374e3c46697136726c Mon Sep 17 00:00:00 2001 From: Hardev Khandhar <54733460+HardevKhandhar@users.noreply.github.com> Date: Mon, 13 Apr 2020 01:39:25 +0530 Subject: [PATCH 42/56] Breadth First Search in Ruby (#2635) * BFS in Ruby * Updated Changes --- Breadth_First_Search/Breadth_First_Search.rb | 92 ++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 Breadth_First_Search/Breadth_First_Search.rb diff --git a/Breadth_First_Search/Breadth_First_Search.rb b/Breadth_First_Search/Breadth_First_Search.rb new file mode 100644 index 0000000000..e2548423c7 --- /dev/null +++ b/Breadth_First_Search/Breadth_First_Search.rb @@ -0,0 +1,92 @@ +## Breadth First Search algorithm in Ruby. + +def breadth_first_search(adj_matrix, source, destination) + node_array = [source] + path = [] + ## puts "\nThe initial NODE ARRAY is #{node_array}." + + loop do + curr_node = node_array.pop + path << curr_node + ## puts "The next node to be checked is #{curr_node}." + + if curr_node.nil? + puts 'Destination Node Not Found!' + return false + + elsif curr_node == destination + puts "\nDestination Node #{curr_node} Found!" + puts "\nThe path between Source Node #{source} and Destination Node #{destination} is:\n #{path}." + return true + + end + + ## puts "\nIterating through the following array:\n #{adj_matrix[curr_node]}" + children = (0..adj_matrix.length - 1).to_a.select do |i| + ## puts "Checking index #{i} whose value is #{adj_matrix[curr_node][i]}" + adj_matrix[curr_node][i] == 1 + + end + + ## puts "\nCHILD ARRAY returned: #{children}" + node_array = children + node_array + ## puts "\nAfter appending CHILD ARRAY, NODE ARRAY is: #{node_array}" + + end + +end + +## Defining Adjacency Matrix by taking user input + +puts "Enter Size of Adjacency Matrix: " +size = gets.to_i + +adj_matrix = Array.new(size) { [] } + +i = 0 +counter = 0 + +while(counter != size) + i = 0 + puts "\nEnter the values of row #{counter + 1}: " + while(i != size) + adj_matrix[counter][i] = gets.to_i + i += 1 + end + counter += 1 +end + +## User input for Source Node and Destination Node + +puts "\nEnter Source Node: " +source = gets.to_i + +puts "\nEnter Destination Node: " +destination = gets.to_i + +## Passing the adjacent matrix, source and destination as arguments to the algorithm. + +breadth_first_search(adj_matrix, source, destination) + +=begin + +Enter Size of Adjacency Matrix: 4 + +Enter the values of row 1: 0 1 1 0 + +Enter the values of row 2: 1 0 0 0 + +Enter the values of row 3: 1 0 1 0 + +Enter the values of row 4: 0 1 0 0 + +Enter Source Node: 0 + +Enter Destination Node: 2 + +Destination Node 2 Found! + +The path between Source Node 0 and Destination Node 2 is: + [0, 2]. + +=end From 914aaea86c7eb112a6bd967bd497c75250ad2d43 Mon Sep 17 00:00:00 2001 From: Hardev Khandhar <54733460+HardevKhandhar@users.noreply.github.com> Date: Mon, 13 Apr 2020 23:13:22 +0530 Subject: [PATCH 43/56] Tree Inorder Traversal In C# (#2723) --- .../Tree_Inorder_Traversal.cs | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 Tree_Inorder_Traversal/Tree_Inorder_Traversal.cs diff --git a/Tree_Inorder_Traversal/Tree_Inorder_Traversal.cs b/Tree_Inorder_Traversal/Tree_Inorder_Traversal.cs new file mode 100644 index 0000000000..0ef48879ea --- /dev/null +++ b/Tree_Inorder_Traversal/Tree_Inorder_Traversal.cs @@ -0,0 +1,173 @@ +/** + Tree Inorder Traversal In C# +*/ + +using System; + +// Node Class To Declare Nodes Of The Tree +class Node +{ + public int data; + public Node left; + public Node right; + + public void display() + { + Console.Write(" ["); + Console.Write(data); + Console.Write("] "); + } +} + +// Tree Class To Declare Binary Search Tree +class Tree +{ + public Node root; + + // Constructor + public Tree() + { + root = null; + } + + public Node ReturnRoot() + { + return root; + } + + // Function To Insert Node Into BST + public void Insert(int id) + { + Node newNode = new Node(); + newNode.data = id; + + if (root == null) + root = newNode; + else + { + Node current = root; + Node parent; + + while (true) + { + parent = current; + if (id < current.data) + { + current = current.left; + if (current == null) + { + parent.left = newNode; + return; + } + } + + else + { + current = current.right; + if (current == null) + { + parent.right = newNode; + return; + } + } + } + } + } + + // Inorder Traversal Function + public void Inorder(Node Root) + { + if (Root != null) + { + Inorder(Root.left); + Console.Write(Root.data + " "); + Inorder(Root.right); + } + } +} + +class InorderTreeProgram +{ + public static void Main(string[] args) + { + // Declaring the Object Of Tree Class + Tree BST = new Tree(); + Console.WriteLine("1. Insert Node"); + Console.WriteLine("2. Display InOrder Traversal"); + Console.WriteLine("3. Exit"); + + while(true) + { + Console.WriteLine("\nEnter your choice: "); + String choice = Console.ReadLine(); + int Choice = int.Parse(choice); + + switch(Choice) + { + case 1: + { + Console.WriteLine("Enter the value to insert node: "); + String val = Console.ReadLine(); + int data = int.Parse(val); + BST.Insert(data); + break; + } + + case 2: + { + Console.WriteLine("\nTree Inorder Traversal: "); + BST.Inorder(BST.ReturnRoot()); + Console.WriteLine(" "); + break; + } + + case 3: + { + Console.WriteLine("Exit"); + System.Environment.Exit(0); + break; + } + } + } + } +} + +/** + +1. Insert Node +2. Display InOrder Traversal +3. Exit + +Enter your choice: 1 +Enter the value to insert node: 30 + +Enter your choice: 1 +Enter the value to insert node: 35 + +Enter your choice: 1 +Enter the value to insert node: 57 + +Enter your choice: 1 +Enter the value to insert node: 15 + +Enter your choice: 1 +Enter the value to insert node: 63 + +Enter your choice: 1 +Enter the value to insert node: 49 + +Enter your choice: 1 +Enter the value to insert node: 77 + +Enter your choice: 1 +Enter the value to insert node: 98 + +Enter your choice: 2 + +Tree Inorder Traversal: +15 30 35 49 57 63 77 98 + +Enter your choice: 3 +Exit + +*/ From ce02b5e8644581ceda0a87942f72ac1fd20b04ec Mon Sep 17 00:00:00 2001 From: riajha02 <32812168+RiaJha02@users.noreply.github.com> Date: Mon, 13 Apr 2020 11:14:13 -0700 Subject: [PATCH 44/56] Adding Backtracking Using Bitmasking (#2583) Squashing Files --- .../Backtrack_using_bitmask.cpp | 48 +++++++++++++++ .../Backtrack_using_bitmask.java | 59 +++++++++++++++++++ .../Backtrack_using_bitmask.py | 46 +++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 Backtracking_using_bitmask/Backtrack_using_bitmask.cpp create mode 100644 Backtracking_using_bitmask/Backtrack_using_bitmask.java create mode 100644 Backtracking_using_bitmask/Backtrack_using_bitmask.py diff --git a/Backtracking_using_bitmask/Backtrack_using_bitmask.cpp b/Backtracking_using_bitmask/Backtrack_using_bitmask.cpp new file mode 100644 index 0000000000..4305948115 --- /dev/null +++ b/Backtracking_using_bitmask/Backtrack_using_bitmask.cpp @@ -0,0 +1,48 @@ +#include +using namespace std; + +#define d (1 << n) - 1 +int cnt = 0; + +/*This is an optimised approach than the normal backtracking approach. +Here we don’t need to write is Safe Position Function +which works in linear time instead we use bitsets which work in O(1) time.*/ + +void solve(int row, int left, int right, int n) +{ + //All rows are occupied,so the solution must be complete + if(row == d) + { + cnt++; + return; + } + + //Gets a bit sequence with "1"s whereever there is an open "slot" + int pos = d & ~(left | row | right); + + //Loops as long as there is a valid place to put another queen. + while(pos > 0) + { + int bit = pos & (-pos); + pos -= bit; + solve(row | bit, (left | bit) << 1, (right | bit) >> 1, n); + } +} + +int main() { + int n; + cin >> n; + solve(0, 0, 0, n); + cout << cnt; +} + +/* +Sample Input: +4 +Sample Output: +2 +Sample Input: +5 +Sample Output: +10 +*/ \ No newline at end of file diff --git a/Backtracking_using_bitmask/Backtrack_using_bitmask.java b/Backtracking_using_bitmask/Backtrack_using_bitmask.java new file mode 100644 index 0000000000..20c064bfb2 --- /dev/null +++ b/Backtracking_using_bitmask/Backtrack_using_bitmask.java @@ -0,0 +1,59 @@ +import java.util.*; +class Solution +{ + //Keeps track of the # of valid solutions + static int ans = 0; + + public static int power(int x, int y) + { + if(y == 0) + return 1; + int result = power(x,y / 2); + if(y % 2 == 0) + return result * result; + else + return x * result * result; + } + //Checks all possible board configurations + public static void solveNQueens(int left, int col, int right, int n, int done) + { + //All columns are occupied, so the solution must be complete + if(col == done) + { + ans++; + return; + } + + //Gets a bit sequence with "1"s where ever there is an open "slot" + int pos = ~(left | col | right) & done; + + //Loops as long as there is a valid place to put another queen. + while(pos > 0) + { + int bit = pos & (-pos); + pos = pos - bit; + solveNQueens((left | bit) >> 1, col | bit, (right | bit) << 1, n, done); + } + } + public static void main(String[] args) + { + Scanner input = new Scanner(System.in); + int n = input.nextInt(); + //Helps identify valid solutions + int done = power(2, n) - 1; + solveNQueens(0, 0, 0, n, done); + System.out.print(ans); + input.close(); + } +}; + +/* +Sample Input: +4 +Sample Output: +2 +Sample Input: +5 +Sample Output: +10 +*/ \ No newline at end of file diff --git a/Backtracking_using_bitmask/Backtrack_using_bitmask.py b/Backtracking_using_bitmask/Backtrack_using_bitmask.py new file mode 100644 index 0000000000..c43de7811b --- /dev/null +++ b/Backtracking_using_bitmask/Backtrack_using_bitmask.py @@ -0,0 +1,46 @@ +# Here we use bit patterns to keep track of queen placements +# for the columns, left diagonals and right diagonals. + +def totalNQueens(n): + #Helps identify valid solutions + all_ones = 2 ** n - 1 + + #Keeps track of the # of valid solutions + count = 0 + + #Checks all possible board configurations + def helper(ld, column, rd): + nonlocal count + #All columns are occupied,so the solution must be complete + if column == all_ones: + count += 1 + return + + #Gets a bit sequence with "1"s whereever there is an open "slot" + possible_slots = ~(ld | column | rd) & all_ones + + #Loops as long as there is a valid place to put another queen. + while possible_slots: + current_bit = possible_slots & -possible_slots + possible_slots -= current_bit + helper( (ld | current_bit) >> 1, column | current_bit, (rd | current_bit) << 1) + + helper(0, 0, 0) + return count + +if __name__ == '__main__': + n = int(input()) + d = (1 << n) - 1 + cnt = totalNQueens(n) + print(cnt) + +''' +Sample Input: +4 +Sample Output: +2 +Sample Input: +5 +Sample Output: +10 +''' \ No newline at end of file From e754eff2766515c48a2e63cc7665aa2b23ac2cb0 Mon Sep 17 00:00:00 2001 From: Raksha <57195964+raksha009@users.noreply.github.com> Date: Tue, 14 Apr 2020 21:52:54 +0530 Subject: [PATCH 45/56] Transpose of matrix in java (#2529) changes made --- Matrix_Operations/Java/Matrix_transpose.java | 63 ++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 Matrix_Operations/Java/Matrix_transpose.java diff --git a/Matrix_Operations/Java/Matrix_transpose.java b/Matrix_Operations/Java/Matrix_transpose.java new file mode 100644 index 0000000000..f24dacd1d7 --- /dev/null +++ b/Matrix_Operations/Java/Matrix_transpose.java @@ -0,0 +1,63 @@ +// Java Program to calculation transpose of a matrix (2D Array) +import java.util.Scanner; + +public class Matrix_transpose { + + // Find transpose of matrix + public static void transpose_matrices(int[][] matrix) { + + int index1, index2; + int[][] matrix_ans = new int[matrix.length][matrix[0].length]; + for ( index1 = 0; index1 < matrix.length; index1 ++) { + for ( index2 = 0; index2 < matrix[0].length; index2++ ) { + matrix_ans[index2][index1] = matrix[index1][index2]; + } + } + + // Print the calculated matrix + for ( index1 = 0; index1 < matrix_ans.length; index1 ++) { + for ( index2 = 0; index2 < matrix_ans[0].length; index2++ ) { + System.out.print( matrix_ans[index1][index2] + " "); + } + System.out.println(); + } + } + + public static void main(String args[]) { + Scanner s = new Scanner(System.in); + + System.out.println(" Enter number of rows "); + int rows = s.nextInt(); + + System.out.println(" Enter number of columns "); + int columns = s.nextInt(); + int[][] matrix = new int[rows][columns]; + + + System.out.println(" Enter elements of matrix "); + for (int i = 0; i < rows; i++) { + for (int j = 0 ; j < columns; j++) { + matrix[i][j] = s.nextInt(); + } + } + transpose_matrices(matrix); + } +} +/* +TEST CASES + +INPUT + Enter number of rows +2 + Enter number of columns +2 + Enter elements of matrix +2 3 +4 5 + +OUTPUT +2 4 +3 5 + +*/ + From b24d034eca76ad1330585f915c6429b68df11204 Mon Sep 17 00:00:00 2001 From: Manish Choudhary <53442020+Manish-cloud@users.noreply.github.com> Date: Tue, 14 Apr 2020 21:58:22 +0530 Subject: [PATCH 46/56] Kruskal Algorithm Implementation in python (#2682) Used disjoint set data structure for Algorithm implementation. --- Kruskal_Algorithm/Kruskal_Algorithm.py | 93 ++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 Kruskal_Algorithm/Kruskal_Algorithm.py diff --git a/Kruskal_Algorithm/Kruskal_Algorithm.py b/Kruskal_Algorithm/Kruskal_Algorithm.py new file mode 100644 index 0000000000..9739098993 --- /dev/null +++ b/Kruskal_Algorithm/Kruskal_Algorithm.py @@ -0,0 +1,93 @@ +#Implementation of Kruskal Algorithm using Disjoint + +graphData = [] +vertices = [] + +class Disjoint: + def __init__(self): + self.sets = [] + + def createSet(self, val): + self.sets.append([val]) + + def getSets(self): + return self.sets + + def findSet(self, val): + for oneSet in self.sets: + if val in oneSet: + return oneSet + + def mergeSets(self, val1, val2): + set1 = self.findSet(val1) + set2 = self.findSet(val2) + if set1 != set2: + set1.extend(set2) + self.sets.remove(set2) + +def kruskalAlgorithm(vertices, graphData): + MST = [] + minimumWeight = 0 + + adisjointSet = Disjoint() # Creating object of disjoint set + for vertex in vertices: + adisjointSet.createSet(vertex) + + graphData.sort() # Sort weights in increasing order + + for weight, vertex1, vertex2 in graphData: + if (adisjointSet.findSet(vertex1) != adisjointSet.findSet(vertex2)): + minimumWeight += weight + MST.append((weight, vertex1, vertex2)) + adisjointSet.mergeSets(vertex1, vertex2) + # To improve efficiency + # when length of disjoint set becomes 1 we can break loop + if (len(adisjointSet.sets) == 1): + break + + print("Minimum Weight : ", minimumWeight) + # To display in which order edges are added + for path in MST: + print((path[1], path[2]), "=>", path[0]) + +if __name__ == "__main__": + numberOfVertices = int(input("Enter number of vertices in graph : ")) + print("Enter vertices") + for _ in range(numberOfVertices): + vertex = input() + vertices.append(vertex) + + numberOfEdges = int(input("Enter number of edges in graph : ")) + print("Note :=> Enter graph data in following format weight vertex1 vertex2") + for _ in range(numberOfEdges): + weights, vertex1, vertex2 = input().split() + weights = int(weights) + graphData.append((weights, vertex1, vertex2)) + + kruskalAlgorithm(vertices, graphData) + +""" +Input/Output + +Enter number of vertices in graph : 5 +Enter vertices +a +b +c +d +e +Enter number of edges in graph : 7 +Note :=> Enter graph data in following format weight vertex1 vertex2 +1 a c +4 a b +2 c b +3 b d +7 c d +5 c e +6 d e +Minimum Weight : 11 +('a', 'c') => 1 +('c', 'b') => 2 +('b', 'd') => 3 +('c', 'e') => 5 +""" From 8d5c048de2e8737a9f1c04cf78b240b719f20380 Mon Sep 17 00:00:00 2001 From: Rukmini Meda <44504940+Rukmini-Meda@users.noreply.github.com> Date: Tue, 14 Apr 2020 22:03:55 +0530 Subject: [PATCH 47/56] squashing commit --- .../Tree_Preorder_Traversal.dart | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 Tree_Preorder_Traversal/Tree_Preorder_Traversal.dart diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.dart b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.dart new file mode 100644 index 0000000000..81898f6cfd --- /dev/null +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.dart @@ -0,0 +1,139 @@ +import 'dart:io'; + +// Class to define the node of a binary tree. +class Node { + + int value; + Node left; + Node right; + + Node(int value) { + + this.value = value; + this.left = null; + this.right = null; + + } + +} + +// Class to define a binary tree. +class Tree { + + // The tree's root. + Node root; + + // Constructor + Tree(Node root) { + this.root = root; + } + + // Insert method to build the tree using recursion. + Node insert(Node root, int val) { + + if (root != null){ + + // Inserting in the left side if value is less than root. + if (val < root.value) { + root.left = insert(root.left, val); + } + else { + // Inserting in the right side if value is greater than root. + if (val > root.value) { + root.right = insert(root.right, val); + } + // Informing user that the value is already present. + else{ + print("Value is already present in the tree."); + } + } + } + else{ + // Insertion + root = Node(val); + } + + return root; + + } + + // Utility method used to print the preorder traversal using recursion. + void preorder_utility(Node node) { + + if (node != null) { + print(node.value); + + // Recursion + preorder_utility(node.left); + preorder_utility(node.right); + } + + } + + // Method to print the preorder traversal of the binary tree. + void tree_preorder_traversal(){ + + print("The preorder traversal of the tree in the given input is follows:"); + preorder_utility(this.root); + + } + +} + +// Driver method of the program +void main(){ + + // Reading user input + print("Enter root of the tree:"); + var input = stdin.readLineSync(); + int root_val = int.parse(input); + + // Root node + Node root_node = Node(root_val); + + // Binary Tree + Tree tree = Tree(root_node); + + String choice = "y"; + + while (choice == "y") { + + print("Enter number to insert:"); + var input3 = stdin.readLineSync(); + int insert_val = int.parse(input3); + tree.insert(root_node, insert_val); + + print("Do you want to insert another number into the tree? (y/n)"); + var input2 = stdin.readLineSync(); + choice = input2; + + } + + /* Sample Input tree + 8 + / \ + 3 12 + / \ / \ + 2 6 9 15 + / \ + 5 7 + */ + + // Calling method to print preorder traversal of the tree. + tree.tree_preorder_traversal(); + + /* Sample Output + The preorder traversal of the tree in the given input is follows: + 8 + 3 + 2 + 6 + 5 + 7 + 12 + 9 + 15 + */ + +} + From f9be0eb8c5cc014879bee91fbac2431fb79c9569 Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Sat, 25 Apr 2020 12:43:00 +0530 Subject: [PATCH 48/56] Revert "squashing commit" This reverts commit 8d5c048de2e8737a9f1c04cf78b240b719f20380. --- .../Tree_Preorder_Traversal.dart | 139 ------------------ 1 file changed, 139 deletions(-) delete mode 100644 Tree_Preorder_Traversal/Tree_Preorder_Traversal.dart diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.dart b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.dart deleted file mode 100644 index 81898f6cfd..0000000000 --- a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.dart +++ /dev/null @@ -1,139 +0,0 @@ -import 'dart:io'; - -// Class to define the node of a binary tree. -class Node { - - int value; - Node left; - Node right; - - Node(int value) { - - this.value = value; - this.left = null; - this.right = null; - - } - -} - -// Class to define a binary tree. -class Tree { - - // The tree's root. - Node root; - - // Constructor - Tree(Node root) { - this.root = root; - } - - // Insert method to build the tree using recursion. - Node insert(Node root, int val) { - - if (root != null){ - - // Inserting in the left side if value is less than root. - if (val < root.value) { - root.left = insert(root.left, val); - } - else { - // Inserting in the right side if value is greater than root. - if (val > root.value) { - root.right = insert(root.right, val); - } - // Informing user that the value is already present. - else{ - print("Value is already present in the tree."); - } - } - } - else{ - // Insertion - root = Node(val); - } - - return root; - - } - - // Utility method used to print the preorder traversal using recursion. - void preorder_utility(Node node) { - - if (node != null) { - print(node.value); - - // Recursion - preorder_utility(node.left); - preorder_utility(node.right); - } - - } - - // Method to print the preorder traversal of the binary tree. - void tree_preorder_traversal(){ - - print("The preorder traversal of the tree in the given input is follows:"); - preorder_utility(this.root); - - } - -} - -// Driver method of the program -void main(){ - - // Reading user input - print("Enter root of the tree:"); - var input = stdin.readLineSync(); - int root_val = int.parse(input); - - // Root node - Node root_node = Node(root_val); - - // Binary Tree - Tree tree = Tree(root_node); - - String choice = "y"; - - while (choice == "y") { - - print("Enter number to insert:"); - var input3 = stdin.readLineSync(); - int insert_val = int.parse(input3); - tree.insert(root_node, insert_val); - - print("Do you want to insert another number into the tree? (y/n)"); - var input2 = stdin.readLineSync(); - choice = input2; - - } - - /* Sample Input tree - 8 - / \ - 3 12 - / \ / \ - 2 6 9 15 - / \ - 5 7 - */ - - // Calling method to print preorder traversal of the tree. - tree.tree_preorder_traversal(); - - /* Sample Output - The preorder traversal of the tree in the given input is follows: - 8 - 3 - 2 - 6 - 5 - 7 - 12 - 9 - 15 - */ - -} - From 8f7946b2cc621f5add3fe9e04f1c9e14dc02b321 Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Sat, 25 Apr 2020 13:42:16 +0530 Subject: [PATCH 49/56] Blank Line Added --- Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js index 2842a2d6cf..615fc2405d 100644 --- a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js @@ -95,4 +95,4 @@ Preorder Traversal: 4 6 -*/ \ No newline at end of file +*/ From 6eba65d00326cf3d884b749d6d949a2ee6e8bed2 Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Sat, 25 Apr 2020 13:52:41 +0530 Subject: [PATCH 50/56] commit4 --- Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js index f891bee41e..615fc2405d 100644 --- a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js @@ -62,7 +62,7 @@ class BinarySearchTree return this.root; } //function of preorder traversal - + preorder(root) { if(root != null) From cdcaa404f0c26365a434a7921908509d9248f7ad Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Sat, 25 Apr 2020 15:15:10 +0530 Subject: [PATCH 51/56] commit5 --- .../Tree_Preorder_Traversal.dart | 139 ------------------ .../Tree_Preorder_Traversal.js.js | 2 +- 2 files changed, 1 insertion(+), 140 deletions(-) delete mode 100644 Tree_Preorder_Traversal/Tree_Preorder_Traversal.dart diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.dart b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.dart deleted file mode 100644 index 81898f6cfd..0000000000 --- a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.dart +++ /dev/null @@ -1,139 +0,0 @@ -import 'dart:io'; - -// Class to define the node of a binary tree. -class Node { - - int value; - Node left; - Node right; - - Node(int value) { - - this.value = value; - this.left = null; - this.right = null; - - } - -} - -// Class to define a binary tree. -class Tree { - - // The tree's root. - Node root; - - // Constructor - Tree(Node root) { - this.root = root; - } - - // Insert method to build the tree using recursion. - Node insert(Node root, int val) { - - if (root != null){ - - // Inserting in the left side if value is less than root. - if (val < root.value) { - root.left = insert(root.left, val); - } - else { - // Inserting in the right side if value is greater than root. - if (val > root.value) { - root.right = insert(root.right, val); - } - // Informing user that the value is already present. - else{ - print("Value is already present in the tree."); - } - } - } - else{ - // Insertion - root = Node(val); - } - - return root; - - } - - // Utility method used to print the preorder traversal using recursion. - void preorder_utility(Node node) { - - if (node != null) { - print(node.value); - - // Recursion - preorder_utility(node.left); - preorder_utility(node.right); - } - - } - - // Method to print the preorder traversal of the binary tree. - void tree_preorder_traversal(){ - - print("The preorder traversal of the tree in the given input is follows:"); - preorder_utility(this.root); - - } - -} - -// Driver method of the program -void main(){ - - // Reading user input - print("Enter root of the tree:"); - var input = stdin.readLineSync(); - int root_val = int.parse(input); - - // Root node - Node root_node = Node(root_val); - - // Binary Tree - Tree tree = Tree(root_node); - - String choice = "y"; - - while (choice == "y") { - - print("Enter number to insert:"); - var input3 = stdin.readLineSync(); - int insert_val = int.parse(input3); - tree.insert(root_node, insert_val); - - print("Do you want to insert another number into the tree? (y/n)"); - var input2 = stdin.readLineSync(); - choice = input2; - - } - - /* Sample Input tree - 8 - / \ - 3 12 - / \ / \ - 2 6 9 15 - / \ - 5 7 - */ - - // Calling method to print preorder traversal of the tree. - tree.tree_preorder_traversal(); - - /* Sample Output - The preorder traversal of the tree in the given input is follows: - 8 - 3 - 2 - 6 - 5 - 7 - 12 - 9 - 15 - */ - -} - diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js index f891bee41e..615fc2405d 100644 --- a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js @@ -62,7 +62,7 @@ class BinarySearchTree return this.root; } //function of preorder traversal - + preorder(root) { if(root != null) From 22548f41bca9f3437e0232d344c2f33d7f6affe4 Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Mon, 27 Apr 2020 09:27:14 +0530 Subject: [PATCH 52/56] js --- .../Tree_Preorder_Traversal.dart | 139 ++++++++++++++++++ ...ersal.js.js => Tree_Preorder_Traversal.js} | 1 - 2 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 Tree_Preorder_Traversal/Tree_Preorder_Traversal.dart rename Tree_Preorder_Traversal/{Tree_Preorder_Traversal.js.js => Tree_Preorder_Traversal.js} (99%) diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.dart b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.dart new file mode 100644 index 0000000000..81898f6cfd --- /dev/null +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.dart @@ -0,0 +1,139 @@ +import 'dart:io'; + +// Class to define the node of a binary tree. +class Node { + + int value; + Node left; + Node right; + + Node(int value) { + + this.value = value; + this.left = null; + this.right = null; + + } + +} + +// Class to define a binary tree. +class Tree { + + // The tree's root. + Node root; + + // Constructor + Tree(Node root) { + this.root = root; + } + + // Insert method to build the tree using recursion. + Node insert(Node root, int val) { + + if (root != null){ + + // Inserting in the left side if value is less than root. + if (val < root.value) { + root.left = insert(root.left, val); + } + else { + // Inserting in the right side if value is greater than root. + if (val > root.value) { + root.right = insert(root.right, val); + } + // Informing user that the value is already present. + else{ + print("Value is already present in the tree."); + } + } + } + else{ + // Insertion + root = Node(val); + } + + return root; + + } + + // Utility method used to print the preorder traversal using recursion. + void preorder_utility(Node node) { + + if (node != null) { + print(node.value); + + // Recursion + preorder_utility(node.left); + preorder_utility(node.right); + } + + } + + // Method to print the preorder traversal of the binary tree. + void tree_preorder_traversal(){ + + print("The preorder traversal of the tree in the given input is follows:"); + preorder_utility(this.root); + + } + +} + +// Driver method of the program +void main(){ + + // Reading user input + print("Enter root of the tree:"); + var input = stdin.readLineSync(); + int root_val = int.parse(input); + + // Root node + Node root_node = Node(root_val); + + // Binary Tree + Tree tree = Tree(root_node); + + String choice = "y"; + + while (choice == "y") { + + print("Enter number to insert:"); + var input3 = stdin.readLineSync(); + int insert_val = int.parse(input3); + tree.insert(root_node, insert_val); + + print("Do you want to insert another number into the tree? (y/n)"); + var input2 = stdin.readLineSync(); + choice = input2; + + } + + /* Sample Input tree + 8 + / \ + 3 12 + / \ / \ + 2 6 9 15 + / \ + 5 7 + */ + + // Calling method to print preorder traversal of the tree. + tree.tree_preorder_traversal(); + + /* Sample Output + The preorder traversal of the tree in the given input is follows: + 8 + 3 + 2 + 6 + 5 + 7 + 12 + 9 + 15 + */ + +} + diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js similarity index 99% rename from Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js rename to Tree_Preorder_Traversal/Tree_Preorder_Traversal.js index 615fc2405d..ffd908bedf 100644 --- a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js @@ -94,5 +94,4 @@ Preorder Traversal: 5 4 6 - */ From 433201fa58e051f0bef41e189ea193f78cd4057c Mon Sep 17 00:00:00 2001 From: monikajha <53649201+m-code12@users.noreply.github.com> Date: Sun, 26 Apr 2020 01:18:13 +0530 Subject: [PATCH 53/56] js --- Heap_Sort/heap_sort.php | 74 ++++++++++++++ Merge_Sort/Merge_Sort.rs | 97 +++++++++++++++++++ Ternary_Search/Ternary_Search.kt | 77 +++++++++++++++ ...ersal.js.js => Tree_Preorder_Traversal.js} | 1 - 4 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 Heap_Sort/heap_sort.php create mode 100644 Merge_Sort/Merge_Sort.rs create mode 100644 Ternary_Search/Ternary_Search.kt rename Tree_Preorder_Traversal/{Tree_Preorder_Traversal.js.js => Tree_Preorder_Traversal.js} (99%) diff --git a/Heap_Sort/heap_sort.php b/Heap_Sort/heap_sort.php new file mode 100644 index 0000000000..f16b141cc9 --- /dev/null +++ b/Heap_Sort/heap_sort.php @@ -0,0 +1,74 @@ + $data[$index]) // If left child is larger than root + $largest = $left; + else + $largest = $index; + + if ($right < $heapSize && $data[$right] > $data[$largest]) // If right child is larger than largest so far + $largest = $right; + + if ($largest != $index) // If largest is not root + { + $temp = $data[$index]; + $data[$index] = $data[$largest]; + $data[$largest] = $temp; + + //Recursively heapify the affected sub-tree + MaxHeapify($data, $heapSize, $largest); + } +} + +function HeapSort(&$data, $count) { + $heapSize = $count; + + // Build heap (rearrange array) + for ($p = ($heapSize - 1) / 2; $p >= 0; $p--) + MaxHeapify($data, $heapSize, $p); + + // One by one extract an element from heap + for ($i = $count - 1; $i > 0; $i--) + { + $temp = $data[$i]; + $data[$i] = $data[0]; + $data[0] = $temp; + + $heapSize--; + MaxHeapify($data, $heapSize, 0); + } +} + +// example of driver function +$array = array(20 , 43 , 65 , 88 , 11 , 33 , 56 , 74); +HeapSort($array , 8); +print_r($array); + + // output + /*Array + ( + [0] => 11 + [1] => 20 + [2] => 33 + [3] => 65 + [4] => 43 + [5] => 56 + [6] => 74 + [7] => 88 + ) + +*/ + +?> diff --git a/Merge_Sort/Merge_Sort.rs b/Merge_Sort/Merge_Sort.rs new file mode 100644 index 0000000000..4ee67d93fe --- /dev/null +++ b/Merge_Sort/Merge_Sort.rs @@ -0,0 +1,97 @@ +/* + Rust Program to implement Merge Sort + -------------------------------------------------------- + Merge Sort + -------------------------------------------------------- +Merge sort is a divide-conquer-combine algorithm based on the idea of breaking down a list into several sub-lists . +The list is broken into sublists until each sublist consists of a single element and merging those sublists in a +manner that results into a sorted list. + +The idea is : + -> Divide the unsorted list into N sublists, each containing 1 element. + -> Take adjacent pairs of two singleton lists and merge them to form a list of 2 elements.N will now convert + into N/2 lists of size 2. + -> Repeat the process till a single sorted list of size N is obtained. + +Complexity Analysis : + +The list of size N is divided into a max of logN parts, and the merging of all sublists into a single list takes O(N) time. +The worst case run time of this algorithm is O(NlogN) . +The average and best case run time of this algorithm is N(logN) . +The space complexity of this algorithm is N . +*/ + + +use std::io; +use std::str::FromStr; + +fn main() { + println!("Enter the numbers to be sorted (separated by space) : "); + let mut i = read_values::().unwrap(); + merge_sort(&mut i); + println!("Sorted array: {:?}", i) + } + +fn merge_sort(a: &mut Vec) { + let size = a.len(); + let mut buffer = vec![0; size]; + merge_split(a, 0, size, &mut buffer); +} + +fn merge_split(a: &mut Vec, start: usize, end: usize, buffer: &mut Vec) { + if end - start > 1 { + // Determine the split index + let split = (start + end) / 2; + + // Split and merge sort + merge_split(a, start, split, buffer); + merge_split(a, split, end, buffer); + merge(a, buffer, start, split, end); + merge_copy(buffer, a, start, end); + } +} + +fn merge(src: &Vec, dest: &mut Vec, start: usize, split: usize, end: usize) { + // Define cursor indices for the left and right part that will be merged + let mut left = start; + let mut right = split; + + // Merge the parts into the destination in the correct order + for i in start..end { + if left < split && (right >= end || src[left] <= src[right]) { + dest[i] = src[left]; + left += 1; + } else { + dest[i] = src[right]; + right += 1; + } + } +} + +fn merge_copy(src: &Vec, dest: &mut Vec, start: usize, end: usize) { + (start..end).for_each(|i| dest[i] = src[i]); +} + +fn read_values() -> Result, T::Err> { + let mut s = String::new(); + io::stdin() + .read_line(&mut s) + .expect("could not read from stdin"); + s.trim() + .split_whitespace() + .map(|word| word.parse()) + .collect() +} + +/* + + Sample Input : + + Enter the numbers to be sorted (separated by space) : + 76 56 45 3 1 4 + + Sample Output : + + Sorted array: [1, 3, 4, 45, 56, 76] +*/ + diff --git a/Ternary_Search/Ternary_Search.kt b/Ternary_Search/Ternary_Search.kt new file mode 100644 index 0000000000..65b82347ad --- /dev/null +++ b/Ternary_Search/Ternary_Search.kt @@ -0,0 +1,77 @@ + import java.util.* + import kotlin.collections.ArrayList + + //Ternary Search begins + public fun ternarySearch(l:Int, r:Int, key:Int, ar:ArrayList): Int { + if(r>=1){ + var mid1 = l + (r - l) / 3 + var mid2 = r - (r - l) / 3 + + //Searching for the key element + if (ar[mid1] == key) { + return mid1 + } + + if (ar[mid2] == key) { + return mid2 + } + + if (key < ar[mid1]) { + return ternarySearch(l, mid1 - 1, key, ar) + } + + else if (key > ar[mid2]) { + return ternarySearch(mid2 + 1, r, key, ar) + } + + else { + return ternarySearch(mid1 + 1, mid2 - 1, key, ar) + } + } + return -1; +} + + //Main function + fun main() { + var l:Int = 0 + var r:Int + var p:Int + var key:Int + var scan1: Scanner = Scanner(System.`in`) + + //var ar = arrayOf(1,2,3,4,5,6,7,8,9,10) + var ar = ArrayList() + + //Taking input from user + println("Enter the number of elements: ") + var n:Int = scan1.nextInt() + var temp:Int + for (i in 1..n) { + temp = scan1.nextInt() + ar.add(temp) + } + + //Sorting the array + println("Sorting the array in ascending order...") + ar.sort() + r = ar.count() + println("Enter the key element to search for:") + key = scan1.nextInt() + p = ternarySearch(l, r, key, ar) + //Printing the key element with its position + print("Index of $key is $p \n") + + + /*Sample Input and Output + Enter the number of elements : + 6 + 5 + 4 + 3 + 2 + 1 + Sorting the array in ascending order... + Enter the key element to search for: + 5 + Index of 5 is 4 + */ diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js similarity index 99% rename from Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js rename to Tree_Preorder_Traversal/Tree_Preorder_Traversal.js index 615fc2405d..ffd908bedf 100644 --- a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js.js +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js @@ -94,5 +94,4 @@ Preorder Traversal: 5 4 6 - */ From 68b58afc5f01100a9e4f176a62aeb4401c5021a4 Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Sat, 9 May 2020 13:49:46 +0530 Subject: [PATCH 54/56] space added in the last line --- Tree_Preorder_Traversal/Tree_Preorder_Traversal.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js index ffd908bedf..615fc2405d 100644 --- a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js @@ -94,4 +94,5 @@ Preorder Traversal: 5 4 6 + */ From 44970309f529c65f34ac8750735d41ae4964e6ff Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Sat, 9 May 2020 16:37:38 +0530 Subject: [PATCH 55/56] js deleted --- .../Tree_Preorder_Traversal.js | 98 ------------------- 1 file changed, 98 deletions(-) delete mode 100644 Tree_Preorder_Traversal/Tree_Preorder_Traversal.js diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js deleted file mode 100644 index 615fc2405d..0000000000 --- a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js +++ /dev/null @@ -1,98 +0,0 @@ - -//Tree_Preorder_Traversal in javascript -class Node -{ - constructor(data) - { - this.data = data; - this.left = null; //left child of the node - this.right = null; //right child of the node - } -} - -class BinarySearchTree -{ - constructor() - { - this.root = null; - } - //data inserting in tree - - insert(data) - { - let node = new Node(data); - if(this.root == null) - { - this.root = node; - } - else - { - this.insertNode(this.root, node); - } - } - - insertNode(root, newNode) - { - if(newNode.data < root.data) - { - if(root.left == null) - { - root.left = newNode; - } - else - { - this.insertNode(root.left, newNode); - } - } - else if(newNode.data > root.data) - { - if(root.right == null) - { - root.right = newNode; - } - else - { - this.insertNode(root.right, newNode); - } - } - } - - getRootNode() - { - return this.root; - } - //function of preorder traversal - - preorder(root) - { - if(root != null) - { - console.log(root.data); // first line - P L R - this.preorder(root.left); // second line - this.preorder(root.right); // third line - } - } -} - -var bst = new BinarySearchTree(); -//tree data insertion statically -bst.insert(3); -bst.insert(5); -bst.insert(1); -bst.insert(6); -bst.insert(4); -var root = bst.getRootNode(); -console.log('Preorder Traversal:'); -bst.preorder(root); -console.log('\n'); - -/* -output: -Preorder Traversal: -3 -1 -5 -4 -6 - -*/ From 97f3c586ace89866513791b4726e732add491fad Mon Sep 17 00:00:00 2001 From: Afroz Quraishi Date: Sat, 9 May 2020 16:53:55 +0530 Subject: [PATCH 56/56] js file added --- .../Tree_Preorder_Traversal.js | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 Tree_Preorder_Traversal/Tree_Preorder_Traversal.js diff --git a/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js new file mode 100644 index 0000000000..a779ea6d58 --- /dev/null +++ b/Tree_Preorder_Traversal/Tree_Preorder_Traversal.js @@ -0,0 +1,99 @@ + + +//Tree_Preorder_Traversal in javascript +class Node +{ + constructor(data) + { + this.data = data; + this.left = null; //left child of the node + this.right = null; //right child of the node + } +} + +class BinarySearchTree +{ + constructor() + { + this.root = null; + } + //data inserting in tree + + insert(data) + { + let node = new Node(data); + if(this.root == null) + { + this.root = node; + } + else + { + this.insertNode(this.root, node); + } + } + + insertNode(root, newNode) + { + if(newNode.data < root.data) + { + if(root.left == null) + { + root.left = newNode; + } + else + { + this.insertNode(root.left, newNode); + } + } + else if(newNode.data > root.data) + { + if(root.right == null) + { + root.right = newNode; + } + else + { + this.insertNode(root.right, newNode); + } + } + } + + getRootNode() + { + return this.root; + } + //function of preorder traversal + + preorder(root) + { + if(root != null) + { + console.log(root.data); // first line - P L R + this.preorder(root.left); // second line + this.preorder(root.right); // third line + } + } +} + +var bst = new BinarySearchTree(); +//tree data insertion statically +bst.insert(3); +bst.insert(5); +bst.insert(1); +bst.insert(6); +bst.insert(4); +var root = bst.getRootNode(); +console.log('Preorder Traversal:'); +bst.preorder(root); +console.log('\n'); + +/* +output: +Preorder Traversal: +3 +1 +5 +4 +6 + +*/ \ No newline at end of file