diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 1f2af51..96cc43e 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -11,6 +11,7 @@ <entry name="!?*.flex" /> <entry name="!?*.kt" /> <entry name="!?*.clj" /> + <entry name="!?*.aj" /> </wildcardResourcePatterns> <annotationProcessing> <profile default="true" name="Default" enabled="false"> diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 97626ba..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project version="4"> - <component name="Encoding"> - <file url="PROJECT" charset="UTF-8" /> - </component> -</project> \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 7ac24c7..fe72da5 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -3,8 +3,9 @@ <component name="GradleSettings"> <option name="linkedExternalProjectsSettings"> <GradleProjectSettings> - <option name="distributionType" value="DEFAULT_WRAPPED" /> + <option name="distributionType" value="LOCAL" /> <option name="externalProjectPath" value="$PROJECT_DIR$" /> + <option name="gradleHome" value="C:\Program Files\Android\Android Studio\gradle\gradle-2.14.1" /> <option name="modules"> <set> <option value="$PROJECT_DIR$" /> diff --git a/.idea/misc.xml b/.idea/misc.xml index 62fabb1..5d19981 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -37,26 +37,10 @@ <ConfirmationsSetting value="0" id="Add" /> <ConfirmationsSetting value="0" id="Remove" /> </component> - <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <output url="file://$PROJECT_DIR$/build/classes" /> </component> <component name="ProjectType"> <option name="id" value="Android" /> </component> - <component name="masterDetails"> - <states> - <state key="ProjectJDKs.UI"> - <settings> - <last-edited>Android API 10 Platform</last-edited> - <splitter-proportions> - <option name="proportions"> - <list> - <option value="0.2" /> - </list> - </option> - </splitter-proportions> - </settings> - </state> - </states> - </component> </project> \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..35eb1dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="VcsDirectoryMappings"> - <mapping directory="$PROJECT_DIR$" vcs="Git" /> + <mapping directory="" vcs="Git" /> </component> </project> \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 604b5f6..12ce42a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -43,4 +43,7 @@ dependencies { } + testCompile 'junit:junit:4.12' + testCompile 'org.mockito:mockito-core:1.10.19' + } diff --git a/app/src/main/assets/desc.json b/app/src/main/assets/desc.json index 72e152b..1e936f0 100644 --- a/app/src/main/assets/desc.json +++ b/app/src/main/assets/desc.json @@ -94,6 +94,16 @@ "<a href='https://github.com/naman14/AlgorithmVisualizer-Android/blob/master/app/src/main/java/com/naman14/algovisualizer/visualizer/SortingVisualizer.java'>SortingVisualizer</a>" ] }, + "merge_sort": { + "Merge Sort": "Merge Sort is a Divide and Conquer algorithm. It divides input array in two halves, calls itself for the two halves and then merges the two sorted halves", + "Complexity": { + "Time": "worst O(n log(n)), best O(n log(n)), average O(n log(n))", + "Space": "worst O(n) auxiliary" + }, + "References": [ + "<a href='https://en.wikipedia.org/wiki/Merge_sort'>Wikipedia<a/><br>" + ] + }, "linked_list": { "Singly linked list": "A Linked List is a linear collection of data elements, called nodes, each pointing to the next node by means of a pointer. It is a data structure consisting of a group of nodes which together represent a sequence. Under the simplest form, each node is composed of data and a reference (in other words, a link) to the next node in the sequence. ", "Complexity": { diff --git a/app/src/main/java/com/naman14/algovisualizer/AlgorithmCode.java b/app/src/main/java/com/naman14/algovisualizer/AlgorithmCode.java index a810f86..f74f931 100644 --- a/app/src/main/java/com/naman14/algovisualizer/AlgorithmCode.java +++ b/app/src/main/java/com/naman14/algovisualizer/AlgorithmCode.java @@ -65,6 +65,42 @@ public class AlgorithmCode { " addLog(\"Array has been sorted\");\n" + " completed();"; + public static final String CODE_MERGE_SORT = "" + + "public void mergeSort(int start, int end){\n" + + " if (start >= end){\n" + + " return;\n" + + " }\n" + + " int middle = (start + end)/2;\n" + + " mergeSort(start,middle);\n" + + " mergeSort(middle+1,end);\n" + + " merge(start,middle,middle+1,end);\n" + + "}\n" + + "public void merge(int start1, int end1, int start2, int end2){\n" + + " List<Integer> sortedList = new ArrayList<Integer>();\n" + + " List<Integer> indexes = new ArrayList<Integer>();\n" + + " int s0 = start1;\n" + + " while(start1 <= end1){\n" + + " if (start2 > end2){\n" + + " sortedList.add(array[start1]);\n" + + " start1+=1;\n" + + " continue;\n" + + " }\n" + + " if (array[start1] <= array[start2]){\n" + + " sortedList.add(array[start1]);\n" + + " start1+=1;\n" + + " }\n" + + " else{\n" + + " sortedList.add(array[start2]);\n" + + " start2+=1;\n" + + " }\n" + + " }\n" + + " int i = 0;\n" + + " for (int number:sortedList) {\n" + + " array[s0+i]=number;\n" + + " i+=1;\n" + + " }\n" + + "}"; + public static final String CODE_BST_SEARCH = " int id = DataUtils.getRandomKeyFromBST();\n" + " addLog(\"Searching for \" + String.valueOf(id));\n" + " BinarySearchTree.Node current = b.getRoot();\n" + diff --git a/app/src/main/java/com/naman14/algovisualizer/CodeFragment.java b/app/src/main/java/com/naman14/algovisualizer/CodeFragment.java index bc3eb40..f443f07 100644 --- a/app/src/main/java/com/naman14/algovisualizer/CodeFragment.java +++ b/app/src/main/java/com/naman14/algovisualizer/CodeFragment.java @@ -67,6 +67,9 @@ public void setCode(String key) { case Algorithm.SELECTION_SORT: addCodeItem(AlgorithmCode.CODE_SELECTION_SORT,"Selection sort"); break; + case Algorithm.MERGE_SORT: + addCodeItem(AlgorithmCode.CODE_MERGE_SORT, "Merge sort"); + break; case Algorithm.BST_SEARCH: addCodeItem(AlgorithmCode.CODE_BST_SEARCH, "BST Search"); break; diff --git a/app/src/main/java/com/naman14/algovisualizer/MainActivity.java b/app/src/main/java/com/naman14/algovisualizer/MainActivity.java index 391868c..1dc72b5 100644 --- a/app/src/main/java/com/naman14/algovisualizer/MainActivity.java +++ b/app/src/main/java/com/naman14/algovisualizer/MainActivity.java @@ -93,6 +93,10 @@ public boolean onChildClick(ExpandableListView expandableListView, View view, in break; case 2: algoFragment.setupFragment(Algorithm.SELECTION_SORT); + break; + case 3: + algoFragment.setupFragment(Algorithm.MERGE_SORT); + break; } break; case 2: @@ -208,6 +212,7 @@ private void prepareListData() { heading2.add("Bubble Sort"); heading2.add("Insertion Sort"); heading2.add("Selection Sort"); + heading2.add("Merge Sort"); List<String> heading3 = new ArrayList<String>(); heading3.add("BST Search"); heading3.add("BST Insert"); diff --git a/app/src/main/java/com/naman14/algovisualizer/VisualAlgoFragment.java b/app/src/main/java/com/naman14/algovisualizer/VisualAlgoFragment.java index d6756d0..dd1243d 100644 --- a/app/src/main/java/com/naman14/algovisualizer/VisualAlgoFragment.java +++ b/app/src/main/java/com/naman14/algovisualizer/VisualAlgoFragment.java @@ -41,6 +41,7 @@ import com.naman14.algovisualizer.algorithm.search.LinearSearch; import com.naman14.algovisualizer.algorithm.sorting.BubbleSort; import com.naman14.algovisualizer.algorithm.sorting.InsertionSort; +import com.naman14.algovisualizer.algorithm.sorting.MergeSort; import com.naman14.algovisualizer.algorithm.sorting.SelectionSort; import com.naman14.algovisualizer.algorithm.tree.bst.BSTAlgorithm; import com.naman14.algovisualizer.visualizer.AlgorithmVisualizer; @@ -190,6 +191,12 @@ public void setupFragment(String algorithmKey) { algorithm = new SelectionSort((SortingVisualizer) visualizer, getActivity(), logFragment); ((SelectionSort) algorithm).setData(DataUtils.createRandomArray(15)); break; + case Algorithm.MERGE_SORT: + visualizer = new SortingVisualizer(getActivity()); + appBarLayout.addView(visualizer); + algorithm = new MergeSort((SortingVisualizer)visualizer, getActivity(), logFragment); + ((MergeSort)algorithm).setData(DataUtils.createRandomArray(15)); + break; case Algorithm.BST_SEARCH: visualizer = new BSTVisualizer(getActivity()); appBarLayout.addView(visualizer); diff --git a/app/src/main/java/com/naman14/algovisualizer/algorithm/Algorithm.java b/app/src/main/java/com/naman14/algovisualizer/algorithm/Algorithm.java index 349452a..080db75 100644 --- a/app/src/main/java/com/naman14/algovisualizer/algorithm/Algorithm.java +++ b/app/src/main/java/com/naman14/algovisualizer/algorithm/Algorithm.java @@ -42,6 +42,7 @@ public class Algorithm extends HandlerThread { public static final String DFS = "dfs"; public static final String DIJKSTRA = "dijkstra"; public static final String BELLMAN_FORD = "bellman_ford"; + public static final String MERGE_SORT = "merge_sort"; public LogFragment logFragment; diff --git a/app/src/main/java/com/naman14/algovisualizer/algorithm/sorting/MergeSort.java b/app/src/main/java/com/naman14/algovisualizer/algorithm/sorting/MergeSort.java new file mode 100644 index 0000000..328807a --- /dev/null +++ b/app/src/main/java/com/naman14/algovisualizer/algorithm/sorting/MergeSort.java @@ -0,0 +1,99 @@ +package com.naman14.algovisualizer.algorithm.sorting; + +import android.app.Activity; + +import com.naman14.algovisualizer.LogFragment; +import com.naman14.algovisualizer.algorithm.Algorithm; +import com.naman14.algovisualizer.algorithm.DataHandler; +import com.naman14.algovisualizer.visualizer.SortingVisualizer; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by sergio on 02/01/17. + */ + +public class MergeSort extends SortAlgorithm implements DataHandler { + + private int[] array; + + public MergeSort(SortingVisualizer visualizer, Activity activity, LogFragment logFragment) { + this.visualizer = visualizer; + this.activity = activity; + this.logFragment = logFragment; + } + + private void sort(){ + logArray("Original array - " ,array); + mergeSort(0,array.length-1); + completed(); + } + + public void mergeSort(int start, int end){ + addLog("Sorting array between " + start + " and " + end); + if (start >= end){ + return; + } + int middle = (start + end)/2; + highlightInterval(start,middle); + sleep(); + mergeSort(start,middle); + highlightInterval(middle+1,end); + sleep(); + mergeSort(middle+1,end); + highlightInterval(start,end); + sleep(); + merge(start,middle,middle+1,end); + } + + public void merge(int start1, int end1, int start2, int end2){ + addLog("merging sub-array " + start1 + " to " + end1 + " and subarray " + start2 + " to " + + end2); + List<Integer> sortedList = new ArrayList<Integer>(); + int s0 = start1; + while(start1 <= end1){ + if (start2 > end2){ + sortedList.add(array[start1]); + start1+=1; + continue; + } + if (array[start1] <= array[start2]){ + sortedList.add(array[start1]); + start1+=1; + } + else{ + sortedList.add(array[start2]); + start2+=1; + } + } + int i = 0; + for (int number:sortedList) { + array[s0+i]=number; + i+=1; + } + sleep(); + } + + @Override + public void run() { + super.run(); + } + + @Override + public void onDataRecieved(Object data) { + super.onDataRecieved(data); + this.array = (int[])data; + + } + + @Override + public void onMessageReceived(String message) { + super.onMessageReceived(message); + if(message.equals(Algorithm.COMMAND_START_ALGORITHM)){ + startExecution(); + sort(); + } + + } +} diff --git a/app/src/main/java/com/naman14/algovisualizer/algorithm/sorting/SortAlgorithm.java b/app/src/main/java/com/naman14/algovisualizer/algorithm/sorting/SortAlgorithm.java index 3b4b3cb..b804e7c 100644 --- a/app/src/main/java/com/naman14/algovisualizer/algorithm/sorting/SortAlgorithm.java +++ b/app/src/main/java/com/naman14/algovisualizer/algorithm/sorting/SortAlgorithm.java @@ -52,6 +52,24 @@ public void run() { }); } + public void highlightInterval(final int start, final int end){ + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + visualizer.highlightInterval(start,end); + } + }); + } + + public void resetInterval(){ + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + visualizer.highlightInterval(-1,-1); + } + }); + } + @Override public void onDataRecieved(Object data) { diff --git a/app/src/main/java/com/naman14/algovisualizer/visualizer/SortingVisualizer.java b/app/src/main/java/com/naman14/algovisualizer/visualizer/SortingVisualizer.java index 709c948..4bebf38 100644 --- a/app/src/main/java/com/naman14/algovisualizer/visualizer/SortingVisualizer.java +++ b/app/src/main/java/com/naman14/algovisualizer/visualizer/SortingVisualizer.java @@ -32,6 +32,8 @@ public class SortingVisualizer extends AlgorithmVisualizer { int highlightPositionOne = -1, highlightPositionTwo = -1; int highlightPosition = -1; int lineStrokeWidth = getDimensionInPixel(10); + int startInterval, endInterval = -1; + public SortingVisualizer(Context context) { super(context); @@ -72,14 +74,23 @@ protected void onDraw(Canvas canvas) { for (int i = 0; i < array.length; i++) { if (i == highlightPositionOne || i == highlightPositionTwo) { - canvas.drawLine(xPos, getHeight() - (float) ((array[i] / 10.0) * getHeight()), xPos, getHeight(), highlightPaintSwap); + canvas.drawLine(xPos, getHeight() - (float) ((array[i] / 10.0) * getHeight()), + xPos, getHeight(), highlightPaintSwap); } else if (i == highlightPosition) - canvas.drawLine(xPos, getHeight() - (float) ((array[i] / 10.0) * getHeight()), xPos, getHeight(), highlightPaintTrace); + canvas.drawLine(xPos, getHeight() - (float) ((array[i] / 10.0) * getHeight()), + xPos, getHeight(), highlightPaintTrace); + else if (startInterval >= 0 && endInterval >= startInterval && + i >= startInterval && i <= endInterval) { + canvas.drawLine(xPos, getHeight() - (float) ((array[i] / 10.0) * getHeight()), + xPos, getHeight(), highlightPaintTrace); + } else { - canvas.drawLine(xPos, getHeight() - (float) ((array[i] / 10.0) * getHeight()), xPos, getHeight(), paint); + canvas.drawLine(xPos, getHeight() - (float) ((array[i] / 10.0) * getHeight()), + xPos, getHeight(), paint); } - canvas.drawText(String.valueOf(array[i]), xPos - lineStrokeWidth / 3, getHeight() - (float) ((array[i] / 10.0) * getHeight()) - 30, textPaint); + canvas.drawText(String.valueOf(array[i]), xPos - lineStrokeWidth / 3, + getHeight() - (float) ((array[i] / 10.0) * getHeight()) - 30, textPaint); xPos += margin + 30; } @@ -111,11 +122,23 @@ public void highlightTrace(int position) { invalidate(); } + public void highlightInterval(int start, int end){ + this.startInterval = start; + this.endInterval = end; + invalidate(); + } + + public void resetHighlightInterval(){ + highlightInterval(-1,-1); + } + @Override public void onCompleted() { this.highlightPosition = -1; this.highlightPositionTwo = -1; this.highlightPositionOne = -1; + this.startInterval = -1; + this.endInterval = -1; invalidate(); } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index eb96b43..e75c5cd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2,4 +2,6 @@ <string name="app_name">AlgorithmVisualizer</string> <string name="action_settings">Settings</string> <string name="report_bugs">Report any bugs <u> here </u></string> + <string name="fabric_api_key">key</string> + <string name="play_billing_license_key">key</string> </resources> diff --git a/app/src/test/java/com/naman14/algovisualizer/MergeSortTest.java b/app/src/test/java/com/naman14/algovisualizer/MergeSortTest.java new file mode 100644 index 0000000..7b6dd51 --- /dev/null +++ b/app/src/test/java/com/naman14/algovisualizer/MergeSortTest.java @@ -0,0 +1,87 @@ +package com.naman14.algovisualizer; + +import android.app.Activity; +import android.content.Context; +import android.content.res.AssetManager; +import android.content.res.Resources; +import android.test.mock.MockContext; + +import com.naman14.algovisualizer.algorithm.sorting.MergeSort; +import com.naman14.algovisualizer.visualizer.SortingVisualizer; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import static junit.framework.Assert.assertEquals; +import static org.mockito.Mockito.when; + +/** + * Created by sergio on 02/01/17. + */ +@RunWith(MockitoJUnitRunner.class) +public class MergeSortTest { + + @Mock + private SortingVisualizer mSortVisualizer; + @Mock + private Activity mActivity; + @Mock + private LogFragment mLogFragment; + + private MergeSort mergeSort; + + public MergeSortTest(){ + + } + + @Before + public void before(){ + mergeSort = new MergeSort(mSortVisualizer, mActivity,mLogFragment); + } + + @Test + public void mergeSort() throws Exception { + int [] array = new int[] {4,1,2,4,6,8,7,10,9}; + int [] sortedArray = new int [] {1,2,4,4,6,7,8,9,10}; + + mergeSort.onDataRecieved(array); + mergeSort.mergeSort(0,array.length-1); + + for (int i = 0; i < array.length; i++) { + assertEquals(array[i],sortedArray[i]); + } + } + + @Test + public void mergeSort_empty_array() throws Exception{ + int [] array = new int[]{}; + mergeSort.onDataRecieved(array); + mergeSort.mergeSort(0,array.length-1); + assertEquals(array.length,0); + } + + @Test + public void mergeSort_one_element_array() throws Exception{ + int [] array = new int[]{1}; + mergeSort.onDataRecieved(array); + mergeSort.mergeSort(0,array.length-1); + assertEquals(array.length,1); + assertEquals(array[0],1); + } + + @Test + public void merge() throws Exception { + + int [] array = new int[] {1,5,6,7,1,2,3,10}; + int [] mergedArray = new int[] {1,1,2,3,5,6,7,10}; + mergeSort.onDataRecieved(array); + mergeSort.merge(1,3,4,6); + + for (int i = 0; i < array.length; i++) { + assertEquals(array[i],mergedArray[i]); + } + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle index e5fbd9f..efa7225 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { maven { url 'https://maven.fabric.io/public' } } dependencies { - classpath 'com.android.tools.build:gradle:2.1.0' + classpath 'com.android.tools.build:gradle:2.2.3' classpath 'io.fabric.tools:gradle:1.+' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c25cec5..625e6f2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Oct 21 11:34:03 PDT 2015 +#Mon Jan 02 13:25:43 GMT 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip