Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • sarafa/p2
  • mertht/p2
  • cse332-19au/p2
  • sandchow/p2
  • hanzhang/p2
  • cse332-19sp/p2
  • cse332-20sp/p2
  • cse332-20su-tasks/p2
  • cse332-20su/p2
  • cse332-21su/p2
  • cse332-21wi/p2
  • cse332-21sp/p2
  • cse332-20au/p2
13 results
Show changes
Commits on Source (56)
Showing
with 1009 additions and 274 deletions
/bin/
.DS_Store
.idea/
*.iml
No preview for this file type
This diff is collapsed.
......@@ -30,11 +30,6 @@ import org.alicebot.ab.MagicBooleans;
import org.alicebot.ab.MagicStrings;
import org.alicebot.ab.PCAIMLProcessorExtension;
import com.google.code.chatterbotapi.ChatterBot;
import com.google.code.chatterbotapi.ChatterBotFactory;
import com.google.code.chatterbotapi.ChatterBotSession;
import com.google.code.chatterbotapi.ChatterBotType;
import cse332.misc.WordReader;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
......@@ -53,7 +48,6 @@ public class ChatWindow {
private final StringBuilder content;
public String theirUsername;
public Chat esession;
public ChatterBotSession csession;
private final WordSuggestor[] markov;
private final UMessageServerConnection connection;
private final SpellingCorrector checker;
......@@ -86,38 +80,12 @@ public class ChatWindow {
this.esession = new Chat(bot);
}
else if (this.theirUsername.equals("cleverbot")) {
ChatterBotFactory factory = new ChatterBotFactory();
ChatterBot bot1;
try {
bot1 = factory.create(ChatterBotType.CLEVERBOT);
this.csession = bot1.createSession();
} catch (Exception e) {
}
}
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
try {
String path = new java.io.File(".").getCanonicalPath();
this.content.append("<link rel='stylesheet' type='text/css' href='file:///"
+ path + "/chat.css'>");
this.content.append("<head>");
this.content.append(
" <script language=\"javascript\" type=\"text/javascript\">");
this.content.append(" function toBottom(){");
this.content
.append(" window.scrollTo(0, document.body.scrollHeight);");
this.content.append(" }");
this.content.append(" </script>");
this.content.append("</head>");
this.content.append("<body onload='toBottom()'>");
} catch (IOException e1) {
}
private void initialize() {
this.frame = new JFrame();
this.frame.setBounds(100, 100, 290, 390);
this.frame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);
......@@ -137,17 +105,28 @@ public class ChatWindow {
gbc_msgScrollPane.gridx = 0;
gbc_msgScrollPane.gridy = 0;
this.chatMessagesPanel = new JFXPanel();
this.frame.getContentPane().add(this.chatMessagesPanel, gbc_msgScrollPane);
Platform.runLater(() -> {
ChatWindow.this.chatMessages = new WebView();
BorderPane borderPane = new BorderPane();
borderPane.setCenter(ChatWindow.this.chatMessages);
Scene scene = new Scene(borderPane, 450, 450);
ChatWindow.this.chatMessagesPanel.setScene(scene);
});
show();
(new Thread() {
public void run() {
try {
String path = new java.io.File(".").getCanonicalPath();
content.append("<link rel='stylesheet' type='text/css' href='file:///"
+ path + "/chat.css'>");
content.append("<head>");
content.append(
" <script language=\"javascript\" type=\"text/javascript\">");
content.append(" function toBottom(){");
content
.append(" window.scrollTo(0, document.body.scrollHeight);");
content.append(" }");
content.append(" </script>");
content.append("</head>");
content.append("<body onload='toBottom()'>");
} catch (IOException e1) {
}
}
}).start();
JPanel suggestionsPanel = new JPanel();
GridBagConstraints gbc_suggestionsPanel = new GridBagConstraints();
......@@ -269,11 +248,29 @@ public class ChatWindow {
}
};
this.frame.addKeyListener(giveFocus);
this.chatMessagesPanel.addKeyListener(giveFocus);
suggestionsPanel.addKeyListener(giveFocus);
myMessagePanel.addKeyListener(giveFocus);
(new Thread() {
public void run() {
chatMessagesPanel = new JFXPanel();
chatMessagesPanel.addKeyListener(giveFocus);
frame.getContentPane().add(chatMessagesPanel, gbc_msgScrollPane);
Platform.runLater(() -> {
ChatWindow.this.chatMessages = new WebView();
BorderPane borderPane = new BorderPane();
borderPane.setCenter(ChatWindow.this.chatMessages);
Scene scene = new Scene(borderPane, 450, 450);
ChatWindow.this.chatMessagesPanel.setScene(scene);
});
}
}).start();
this.frame.pack();
show();
this.myMessage.requestFocusInWindow();
}
......@@ -322,13 +319,15 @@ public class ChatWindow {
String text = ("SOL " + this.myMessage.getText()).trim();
int lastSpace = text.lastIndexOf(' ');
String allButLast = lastSpace > -1 ? text.substring(0, lastSpace) : null;
this.undo = this.myMessage.getText();
String newText = (allButLast.replaceAll("SOL", "") + " " + result).trim();
if (this.myMessage.getText().startsWith(newText)) {
return false;
if (allButLast != null) {
this.undo = this.myMessage.getText();
String newText = (allButLast.replaceAll("SOL", "") + " " + result).trim();
if (this.myMessage.getText().startsWith(newText)) {
return false;
}
this.myMessage.setText(newText);
return true;
}
this.myMessage.setText(newText);
return true;
}
return false;
}
......@@ -374,13 +373,6 @@ public class ChatWindow {
receiveMessage(this.esession.multisentenceRespond(msg));
return;
}
else if (this.theirUsername.equals("cleverbot")) {
try {
receiveMessage(this.csession.think(msg));
return;
} catch (Exception e) {
}
}
else {
try {
this.connection.m_channel(this.theirUsername, msg);
......
......@@ -15,7 +15,6 @@ import javax.swing.JList;
import p2.wordsuggestor.WordSuggestor;
public class MainWindow {
private JFrame frame;
private List<String> usernames;
private final List<ChatWindow> chats;
......@@ -51,27 +50,30 @@ public class MainWindow {
list.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
@SuppressWarnings("unchecked")
JList<String> list = (JList<String>) e.getSource();
if (e.getClickCount() == 2) {
int index = list.locationToIndex(e.getPoint());
for (ChatWindow client : MainWindow.this.chats) {
if (client.theirUsername
.equals(MainWindow.this.usernames.get(index))) {
client.show();
return;
(new Thread() {
public void run() {
@SuppressWarnings("unchecked")
JList<String> list = (JList<String>) e.getSource();
if (e.getClickCount() == 2) {
int index = list.locationToIndex(e.getPoint());
for (ChatWindow client : MainWindow.this.chats) {
if (client.theirUsername
.equals(MainWindow.this.usernames.get(index))) {
client.show();
return;
}
}
MainWindow.this.chats
.add(new ChatWindow(MainWindow.this.usernames.get(index),
MainWindow.this.markov, MainWindow.this.connection));
}
}
MainWindow.this.chats
.add(new ChatWindow(MainWindow.this.usernames.get(index),
MainWindow.this.markov, MainWindow.this.connection));
}
}).start();
}
});
this.usernames = new ArrayList<String>();
this.usernames.add("cleverbot");
this.usernames.add("eliza");
this.model = new UsersModel(this.usernames);
list.setModel(this.model);
......@@ -86,6 +88,9 @@ public class MainWindow {
}
usersSet.remove(this.username);
this.usernames = new ArrayList<String>(usersSet);
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
this.model.update(this.usernames);
}
......
......@@ -6,16 +6,24 @@ import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.BorderLayout;
import java.io.IOException;
import java.util.function.Supplier;
import javax.swing.Box;
import javafx.embed.swing.JFXPanel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JDialog;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import cse332.interfaces.misc.Dictionary;
import cse332.types.AlphabeticString;
......@@ -62,35 +70,66 @@ public class uMessage {
}
@Override
public void run() {
int N = uMessage.N;
try {
uMessage.markov[this.i] = new WordSuggestor(uMessage.CORPUS, N - this.i,
4, uMessage.NEW_OUTER, uMessage.NEW_INNER);
uMessage.loading[this.i] = false;
this.window.update();
} catch (IOException e) {
public void run() {
int N = uMessage.N;
try {
uMessage.markov[this.i] = new WordSuggestor(uMessage.CORPUS, N - this.i,
4, uMessage.NEW_OUTER, uMessage.NEW_INNER);
this.window.update();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
final uMessage window = new uMessage();
window.frmUmessageLogin.setVisible(true);
window.errors.setText("Loading the Markov Data (n = " + uMessage.N + ")...");
uMessage.markov = new WordSuggestor[uMessage.N];
uMessage.loading = new boolean[uMessage.N];
for (int i1 = 0; i1 < uMessage.N; i1++) {
uMessage.loading[i1] = true;
(new Thread() {
public void run() {
new JFXPanel();
}
for (int i2 = 0; i2 < uMessage.N; i2++) {
new Thread(new MarkovLoader(window, i2)).start();
}).start();
final uMessage window = new uMessage();
markov = new WordSuggestor[uMessage.N];
JDialog dialog = new JDialog((JFrame)null, "Please wait...", true);//true means that the dialog created is modal
JLabel lblStatus = new JLabel("<html><b>Loading Markov Data (n = " + uMessage.N + ")...</b><br>Depending on the data structures you're using<br>" +
"and your computer, this might take a bit.</html>");
JProgressBar pbProgress = new JProgressBar(0, 100);
pbProgress.setIndeterminate(true); //we'll use an indeterminate progress bar
dialog.add(BorderLayout.NORTH, lblStatus);
dialog.add(BorderLayout.CENTER, pbProgress);
dialog.addWindowListener(new WindowAdapter() {
@Override public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
dialog.setSize(300, 90);
SwingWorker<Void, Void> sw = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
for (int i2 = 1; i2 < uMessage.N; i2++) {
new Thread(new MarkovLoader(window, i2)).start();
}
new MarkovLoader(window, 0).run();
return null;
}
@Override
protected void done() {
dialog.dispose();//close the modal dialog
window.frmUmessageLogin.setVisible(true);
}
};
sw.execute(); // this will start the processing on a separate thread
dialog.setVisible(true); //this will block user input as long as the processing task is working
}
/**
......@@ -112,7 +151,7 @@ public class uMessage {
gridBagLayout.columnWidths = new int[] { 0, 90, 90, 90, 0, 0 };
gridBagLayout.rowHeights = new int[] { 0, 9, 0, 0 };
gridBagLayout.columnWeights = new double[] { 0.0, 0.0, 1.0, 0.0, 0.0,
Double.MIN_VALUE };
Double.MIN_VALUE };
gridBagLayout.rowWeights = new double[] { 0.0, 0.0, 0.0, Double.MIN_VALUE };
this.frmUmessageLogin.getContentPane().setLayout(gridBagLayout);
......@@ -131,7 +170,7 @@ public class uMessage {
this.frmUmessageLogin.getContentPane().add(this.horizontalStrut,
gbc_horizontalStrut);
JLabel usernameLabel = new JLabel("Username:");
JLabel usernameLabel = new JLabel("UWnetID:");
GridBagConstraints gbc_usernameLabel = new GridBagConstraints();
gbc_usernameLabel.fill = GridBagConstraints.BOTH;
gbc_usernameLabel.insets = new Insets(0, 0, 5, 5);
......@@ -143,10 +182,14 @@ public class uMessage {
this.username.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
if (update() && e.getKeyCode() == KeyEvent.VK_ENTER) {
uMessage.this.login.setEnabled(false);
login();
}
(new Thread() {
public void run() {
if (update() && e.getKeyCode() == KeyEvent.VK_ENTER) {
uMessage.this.login.setEnabled(false);
login();
}
}
}).start();
}
});
......@@ -187,14 +230,6 @@ public class uMessage {
}
public boolean update() {
boolean noneLoading = true;
for (int i = 0; i < uMessage.loading.length; i++) {
noneLoading &= !uMessage.loading[i];
}
if (noneLoading) {
this.errors.setText("");
this.errors.setForeground(Color.BLACK);
}
if (!this.loggingIn && this.username.getText().length() > 0) {
this.login.setEnabled(true);
this.errors.setForeground(Color.BLACK);
......@@ -210,11 +245,10 @@ public class uMessage {
this.loggingIn = true;
update();
try {
this.connection = new UMessageServerConnection(this,
this.username.getText().replaceAll(" ", ""));
this.connection.go();
} catch (IOException e1) {
}
connection = new UMessageServerConnection(uMessage.this,
username.getText().replaceAll(" ", ""));
connection.go();
} catch (IOException e1) {}
}
public void badNick() {
......@@ -225,19 +259,6 @@ public class uMessage {
}
public void loggedIn(String username) {
boolean noneLoading = false;
while (!noneLoading) {
noneLoading = true;
for (int i = 0; i < uMessage.loading.length; i++) {
noneLoading &= !uMessage.loading[i];
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
this.frmUmessageLogin.dispose();
this.window = new MainWindow(username, uMessage.markov, this.connection);
this.loggingIn = false;
......
......@@ -49,7 +49,7 @@ public class BinarySearchTree<K extends Comparable<K>, V>
}
}
private BSTNode find(K key, V value) {
protected BSTNode find(K key, V value) {
BSTNode prev = null;
BSTNode current = this.root;
......@@ -89,6 +89,9 @@ public class BinarySearchTree<K extends Comparable<K>, V>
@Override
public V find(K key) {
if (key == null) {
throw new IllegalArgumentException();
}
BSTNode result = find(key, null);
if (result == null) {
return null;
......@@ -98,6 +101,9 @@ public class BinarySearchTree<K extends Comparable<K>, V>
@Override
public V insert(K key, V value) {
if (key == null || value == null) {
throw new IllegalArgumentException();
}
BSTNode current = find(key, value);
V oldValue = current.value;
current.value = value;
......
......@@ -6,7 +6,7 @@ import cse332.datastructures.trees.BinarySearchTree;
* TODO: Replace this comment with your own as appropriate.
*
* AVLTree must be a subclass of BinarySearchTree<E> and must use
* inheritance and callst o superclass methods to avoid unnecessary
* inheritance and calls to superclass methods to avoid unnecessary
* duplication or copying of functionality.
*
* 1. Create a subclass of BSTNode, perhaps named AVLNode.
......
......@@ -14,11 +14,16 @@ import cse332.interfaces.misc.Dictionary;
* restrict the size of the input domain (i.e., it must accept
* any key) or the number of inputs (i.e., it must grow as necessary).
* 3. Your HashTable should rehash as appropriate (use load factor as
* shown in class).
* 5. HashTable should be able to grow at least up to 200,000 elements.
* shown in class!).
* 5. HashTable should be able to resize its capacity to prime numbers for more
* than 200,000 elements. After more than 200,000 elements, it should
* continue to resize using some other mechanism.
* 6. We suggest you hard code some prime numbers. You can use this
* list: http://primes.utm.edu/lists/small/100000.txt
* NOTE: Do NOT copy the whole list!
* 7. When implementing your iterator, you should NOT copy every item to another
* dictionary/list and return that dictionary/list's iterator.
*/
public class ChainingHashTable<K, V> extends DeletelessDictionary<K, V> {
private Supplier<Dictionary<K, V>> newChain;
......
......@@ -9,14 +9,16 @@ import cse332.interfaces.misc.DeletelessDictionary;
/**
* TODO: Replace this comment with your own as appropriate.
* 1. The list is typically not sorted.
* 2. Add new items to the front oft he list.
* 2. Add new items to the front of the list.
* 3. Whenever find is called on an item, move it to the front of the
* list. This means you remove the node from its current position
* and make it the first node in the list.
* 4. You need to implement an iterator. The iterator SHOULD NOT move
* elements to the front. The iterator should return elements in
* the order they are stored in the list, starting with the first
* element in the list.
* element in the list. When implementing your iterator, you should
* NOT copy every item to another dictionary/list and return that
* dictionary/list's iterator.
*/
public class MoveToFrontList<K, V> extends DeletelessDictionary<K, V> {
@Override
......
......@@ -3,10 +3,12 @@ package p2.clients;
import java.io.IOException;
import java.util.function.Supplier;
import cse332.datastructures.trees.BinarySearchTree;
import cse332.interfaces.misc.BString;
import cse332.interfaces.misc.Dictionary;
import cse332.types.AlphabeticString;
import cse332.types.NGram;
import datastructures.dictionaries.AVLTree;
import datastructures.dictionaries.ChainingHashTable;
import datastructures.dictionaries.HashTrieMap;
import p2.wordsuggestor.WordSuggestor;
......@@ -20,6 +22,17 @@ public class NGramTester {
Supplier<Dictionary<K, V>> constructor) {
return () -> new ChainingHashTable<K, V>(constructor);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static <K, V> Supplier<Dictionary<K, V>> binarySearchTreeConstructor() {
return () -> new BinarySearchTree();
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public static <K, V> Supplier<Dictionary<K, V>> avlTreeConstructor() {
return () -> new AVLTree();
}
public static void main(String[] args) {
try {
......
package p2.wordsuggestor;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Stack;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import cse332.interfaces.worklists.LIFOWorkList;
import datastructures.worklists.ArrayStack;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.json.simple.JSONArray;
public final class ParseFBMessages {
private ParseFBMessages() {
/* should not be instantiated */ }
// INSTRUCTIONS:
//
// <Your FB Name> may be either:
// 1) Your name on Messenger (e.g. "Danny Allen")
// 2) Your username on facebook, which can be found by looking at the URL on your profile
// It's typically 1), but for whatever reason Facebook sometimes labels them
// with 2) (sorry!). You can check which one your messages are labeled with by
// opening up one of the message files and taking a look.
//
// <Your FB Archive> is the directory on your computer where the archive is stored.
// (e.g. "/Users/Me/Downloads/MyArchiveName" or "C:\Users\Me\Downloads\MyArchiveName")
// You may be able to use a relative path like "./MyArchiveName", but results can
// vary from machine to machine.
//
// DO NOT PUSH YOUR ME.TXT FILE TO GITLAB. WE DO NOT WANT YOUR PRIVATE CONVERSATIONS!!!!
public static void main(String[] args) throws IOException {
if (args.length != 2) {
System.out.println("USAGE: ParseFBMessages <Your FB Name> <Your FB Archive>");
System.exit(1);
}
String name = args[0];
String archive = args[1];
String name = "<Your FB Name>"; // e.g. "Ruth Anderson"
String archive = "<Your FB Archive>"; // e.g. "/Users/rea/workspace/332/facebook-rea/messages"
LIFOWorkList<String> messages = new ArrayStack<String>();
Document doc = Jsoup
.parse(new File(archive + File.separator + "html/messages.htm"), "UTF-8");
Elements messagesElements = doc.getElementsByTag("p");
Stack<String> corpus = new Stack<>();
File[] listOfFiles = (new File(archive + File.separator + "inbox")).listFiles();
for (Element content : messagesElements) {
if (content.previousElementSibling().getElementsByClass("user").text()
.equals(name)) {
messages.add(content.text());
for (int i = 0; i < listOfFiles.length; i++) {
File conversation = new File(listOfFiles[i], "message.json");
if (conversation.isFile()) {
try {
JSONObject obj = (JSONObject) new JSONParser().parse(new FileReader(conversation));
JSONArray messages = (JSONArray) obj.get("messages");
for (Object m: messages) {
JSONObject msg = (JSONObject) m;
String sender = (String) msg.get("sender_name");
if(sender != null && sender.equals(name)) {
corpus.push((String) msg.get("content"));
}
}
} catch (ParseException e) {
System.err.println("Could not parse: " + conversation.toString());
}
}
}
PrintWriter out = new PrintWriter("me.txt", "UTF-8");
while (messages.hasWork()) {
out.println(messages.next());
while (!corpus.isEmpty()) {
out.println(corpus.pop());
}
out.close();
......
......@@ -15,7 +15,6 @@ import datastructures.worklists.ArrayStack;
/**
* An executable that generates text in the style of the provided input file.
* You will need to modify this file.
*/
public class WordSuggestor {
private final int N, K;
......@@ -73,6 +72,12 @@ public class WordSuggestor {
words[i] = allWords.next();
i--;
}
for (i = 0; i < words.length; i++) {
if (words[i] == null) {
words[i] = "NULL";
}
}
return new NGram(words);
}
......
# Project 2 (uMessage) Write-Up #
--------
## Project Enjoyment ##
- How Was Your Partnership?
<pre>TODO</pre>
- What was your favorite part of the project?
<pre>TODO</pre>
- What was your least favorite part of the project?
<pre>TODO</pre>
- How could the project be improved?
<pre>TODO</pre>
- Did you enjoy the project?
<pre>TODO</pre>
-----
## Experiments ##
Throughout p1 and p2, you have written (or used) several distinct implementations of the Dictionary interface:
- HashTrieMap
- MoveToFrontList
- BinarySearchTree
- AVLTree
- ChainingHashTable
In this Write-Up, you will compare various aspects of these data structures. This will take a significant amount of
time, and you should not leave it to the last minute. For each experiment, we expect you to:
- Explain how you constructed the inputs to make your conclusions
- Explain why your data supports your conclusions
- Explain your methodology (e.g., if we wanted to re-run your experiment, we would be able to)
- Include the inputs themselves in the experiments folder
- Include your data either directly in the write-up or in the experiments folder
- If you think it helps your explanation, you can include graphs of the outputs (we recommend that you do this for some of them)
- We recommend that you keep your "N" (as in "N-gram") constant throughout these experiments. (N = 2 and N = 3 are reasonable.)
### BST vs. AVLTree ###
Construct input files to NGramTester of your choosing to demonstrate that an AVL Tree is asymptotically better
than a Binary Search Tree.
<pre>TODO</pre>
### BST Worst Case vs. BST Best Case ###
We know that the worst case for a BST insertion is O(n) and the best case is O(lg n). Construct input
files of your choosing that demonstrate these best and worst cases for a large n. How big is the difference?
Is it surprising?
<pre>TODO</pre>
### ChainingHashTable ###
Your ChainingHashTable should take as an argument to its constructor the type of "chains" it uses. Determine
which type of chain is (on average) best: an MTFList, a BST, or an AVL Tree. Explain your intuition on why
the answer you got makes sense (or doesn't!).
<pre>TODO</pre>
### Hash Functions ###
Write a new hash function (it doesn't have to be any good, but remember to include the code in your repository).
Compare the runtime of your ChainingHashTable when the hash function is varied. How big of a difference can the
hash function make? (You should keep all other inputs (e.g., the chain type) constant.)
<pre>TODO</pre>
### General Purpose Dictionary ###
Compare all of the dictionaries (on their best settings, as determined above) on several large input files. Is
there a clear winner? Why or why not? Is the winner surprising to you?
<pre>TODO</pre>
### General Sorts ###
You have several general purpose sorts (InsertionSort, HeapSort, TopKSort). We would like you to compare these
sorts using *step counting*. That is, for all other experiments, you likely compared the time it took for the various
things to run, but for this one, we want you to (1) choose a definition of step, (2) modify the sorting algorithms to
calculate the number of steps, and (3) compare the results. In this case, there is a "good" definition of step, and
there are many bad ones. We expect you to justify your choice.
<pre>TODO</pre>
### Top K Sort ###
TopKSort should theoretically be better for small values of k. Determine (using timing or step-counting--your choice)
which n (input size) and k (number of elements sorted) makes TopKSort worthwhile over your best sort from the previous
experiment.
<pre>TODO</pre>
### uMessage ###
Use uMessage to test out your implementations. Using N=3, uMessage should take less than a minute to load using
your best algorithms and data structures on a reasonable machine.
- How are the suggestions uMessage gives with the default corpus?
<pre>TODO</pre>
- Now, switch uMessage to use a corpus of YOUR OWN text. To do this, you will need a corpus.
You can use anything you like (Facebook, google talk, e-mails, etc.) We provide
instructions and a script to format Facebook data correctly as we expect it will be the most common
choice. If you are having problems getting data, please come to office hours and ask for help.
Alternatively, you can concatenate a bunch of English papers you've written together to get a corpus
of your writing. PLEASE DO NOT INCLUDE "me.txt" IN YOUR REPOSITORY. WE DO NOT WANT YOUR PRIVATE CONVERSATIONS.
* Follow these instructions to get your Facebook data: https://www.facebook.com/help/212802592074644
* Run the ParseFBMessages program in the main package.
* Use the output file "me.txt" as the corpus for uMessage.
- How are the suggestions uMessage gives wth the new corpus?
<pre>TODO</pre>
-----
## Above and Beyond ##
- Did you do any Above and Beyond? Describe exactly what you implemented.
<pre>TODO</pre>
\ No newline at end of file
......@@ -23,7 +23,7 @@ public class CircularArrayComparatorTests extends TestsUtility {
test("test_a_aa");
test("test_equality_consistent_with_compare");
test("test_compare_transitive");
test("test_equals_doesnt_modify");
finish();
}
......@@ -110,4 +110,13 @@ public class CircularArrayComparatorTests extends TestsUtility {
l2.add("b");
return l1.equals(l2) && l1.compareTo(l2) == 0 ? 1 : 0;
}
public static int test_equals_doesnt_modify() {
CircularArrayFIFOQueue<String> l1 = init();
CircularArrayFIFOQueue<String> l2 = init();
l1.add("a");
l2.add("a");
l1.equals(l2);
return l1.size() == 1 ? 1 : 0;
}
}
......@@ -2,7 +2,7 @@ package tests.gitlab.ckpt1;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.TreeMap;
import java.util.Map;
import java.util.function.Supplier;
......@@ -10,16 +10,16 @@ import cse332.datastructures.containers.Item;
import cse332.interfaces.misc.Dictionary;
import cse332.types.AlphabeticString;
import cse332.types.NGram;
import datastructures.dictionaries.HashTrieMap;
import cse332.datastructures.trees.BinarySearchTree;
import p2.wordsuggestor.NGramToNextChoicesMap;
import tests.TestsUtility;
public class NGramToNextChoicesMapTests extends TestsUtility {
private static Supplier<Dictionary<NGram, Dictionary<AlphabeticString, Integer>>> newOuter =
() -> new HashTrieMap<String, NGram, Dictionary<AlphabeticString, Integer>>(NGram.class);
() -> new BinarySearchTree();
private static Supplier<Dictionary<AlphabeticString, Integer>> newInner =
() -> new HashTrieMap<Character, AlphabeticString, Integer>(AlphabeticString.class);
private static Supplier<Dictionary<AlphabeticString, Integer>> newInner =
() -> new BinarySearchTree();
public static void main(String[] args) {
new NGramToNextChoicesMapTests().run();
......@@ -95,7 +95,7 @@ public class NGramToNextChoicesMapTests extends TestsUtility {
if (items.length != answer.length) return 0;
String[] itemsWithoutCounts = new String[items.length];
for (int j = 0; j < answer.length; j++) {
if (items[j].value != 1) return 0;
if (!items[j].value.equals(1)) return 0;
itemsWithoutCounts[j] = items[j].key;
}
Arrays.sort(itemsWithoutCounts);
......@@ -127,10 +127,10 @@ public class NGramToNextChoicesMapTests extends TestsUtility {
return 1;
}
// TODO: Not finished yet
@SuppressWarnings("unchecked")
public static int testRepeatedWordsPerNGram() {
NGramToNextChoicesMap map = init();
// Creates Ngrams to test for with N = 3
NGram[] ngrams = new NGram[]{
new NGram(new String[]{"foo", "bar", "baz"}),
new NGram(new String[]{"fee", "fi", "fo"}),
......@@ -138,7 +138,7 @@ public class NGramToNextChoicesMapTests extends TestsUtility {
new NGram(new String[]{"3", "2", "2"}),
new NGram(new String[]{"a", "s", "d"})
};
// Array of words seen after each Ngram with correlating index from above
String[][] words = new String[][] {
new String[]{"bop", "bip", "boop", "bop", "bop"},
new String[]{"fum", "giants", "giants"},
......@@ -148,7 +148,10 @@ public class NGramToNextChoicesMapTests extends TestsUtility {
};
// yes this is awful, but i can't think of a better way to do it atm
Map<NGram, Item<String, Integer>[]> answers = new HashMap<>();
// Creates answers for getCountsAfter - Word seen after and count
// corrlates with words and ngrams above
// Note that words after are in sorted order, not in order of array in words
Map<NGram, Item<String, Integer>[]> answers = new TreeMap<>();
answers.put(ngrams[0], (Item<String, Integer>[]) new Item[3]);
answers.get(ngrams[0])[0] = new Item<String, Integer>("bip", 1);
answers.get(ngrams[0])[1] = new Item<String, Integer>("boop", 1);
......@@ -167,12 +170,14 @@ public class NGramToNextChoicesMapTests extends TestsUtility {
answers.get(ngrams[4])[1] = new Item<String, Integer>("for", 2);
answers.get(ngrams[4])[2] = new Item<String, Integer>("while", 2);
// Adds nGrams and words after to student's NGramToNextChoicesMap
for (int i = 0; i < ngrams.length; i++) {
for (int j = 0; j < words[i].length; j++) {
map.seenWordAfterNGram(ngrams[i], words[i][j]);
}
}
// checks to see if getCountsAfter returns correctly
for (int i = 0; i < ngrams.length; i++) {
NGram ngram = ngrams[i];
Item<String, Integer>[] results = map.getCountsAfter(ngram);
......@@ -187,12 +192,15 @@ public class NGramToNextChoicesMapTests extends TestsUtility {
});
Item<String, Integer>[] expected = answers.get(ngram);
// checks for correct number of unique words after
if (results.length != expected.length) return 0;
for (int j = 0; j < expected.length; j++) {
// checks if correct word after via sorted words
if (!expected[j].key.equals(results[j].key)) {
return 0;
}
if (expected[j].value != results[j].value) {
// checks if correct count for given word after
if (!expected[j].value.equals(results[j].value)) {
return 0;
}
}
......
......@@ -139,6 +139,7 @@ public class AVLTreeTests extends TestsUtility {
// Check for accuracy
passed &= totalCount == (n * (n + 1)) / 2 * 5;
passed &= tree.size() == n;
passed &= tree.find("00851") != null;
passed &= tree.find("00851") == 4260;
return passed ? 1 : 0;
......
package tests.gitlab.ckpt2;
import cse332.types.AlphabeticString;
import datastructures.dictionaries.HashTrieMap;
import tests.TestsUtility;
import java.util.HashMap;
import java.util.Map;
public class HashTrieMapTests extends TestsUtility {
protected static HashTrieMap<Character, AlphabeticString, String> STUDENT;
public static void main(String[] args) {
new HashTrieMapTests().run();
}
public static void init() {
STUDENT = new HashTrieMap<>(AlphabeticString.class);
}
@Override
protected void run() {
SHOW_TESTS = true;
PRINT_TESTERR = true;
DEBUG = true;
test("testBasic");
test("testBasicDelete");
test("testFindPrefixes");
test("testFindNonexistentDoesNotCrash");
test("testFindingNullEntriesCausesError");
test("testInsertReplacesOldValue");
test("testInsertingNullEntriesCausesError");
test("testDeleteAll");
test("testDeleteNothing");
test("testDeleteAndInsertSingleChars");
test("testDeleteWorksWhenTrieHasNoBranches");
test("testDeletingAtRoot");
test("testDeletingEmptyString");
test("testDeletingNullEntriesCausesError");
test("testClear");
test("checkUnderlyingStructure");
test("stressTest");
finish();
}
/**
* Tests if insert, find, and findPrefix work in general.
*/
public static int testBasic() {
String[] words = {"dog", "doggy", "doge", "dragon", "cat", "draggin"};
String[] invalid = {"d", "cataract", "", "do"};
addAll(STUDENT, words);
return (containsAllPaths(STUDENT, words) && doesNotContainAll(STUDENT, invalid)) ? 1 : 0;
}
/**
* Checks to see if basic delete functionality works.
*/
public static int testBasicDelete() {
String[] words = {"dog", "doggy", "dreamer", "cat"};
addAll(STUDENT, words);
if (!containsAllPaths(STUDENT, words)) {
return 0;
}
STUDENT.delete(a("I don't exist"));
STUDENT.delete(a("dreamer"));
if (!containsAllPaths(STUDENT, "dog", "doggy", "cat") &&
!containsAllPrefixes(STUDENT, "dreamer", "dreame", "dream", "drea", "dre", "dr") &&
!STUDENT.findPrefix(a("d"))) {
return 0;
}
STUDENT.delete(a("dog"));
if (!containsAllPaths(STUDENT, "doggy", "cat")) {
return 0;
}
STUDENT.delete(a("doggy"));
return containsAllPaths(STUDENT, "cat") ? 1 : 0;
}
/**
* Test findPrefix more rigorously.
*/
public static int testFindPrefixes() {
String[] words = {"dog", "doggy", "doge", "dragon", "cat", "draggin"};
addAll(STUDENT, words);
boolean allPrefixesFound = containsAllPrefixes(STUDENT, "d", "", "do");
boolean invalidPrefixesIgnored = doesNotContainAllPrefixes(STUDENT, "batarang", "dogee", "dragging");
return allPrefixesFound && invalidPrefixesIgnored ? 1 : 0;
}
/**
* Tests that trying to find a non-existent entity does the correct thing
*/
public static int testFindNonexistentDoesNotCrash() {
addAll(STUDENT, "foo", "bar", "baz");
return STUDENT.find(a("orangutan")) == null && STUDENT.find(a("z")) == null &&
STUDENT.find(a("ba")) == null && STUDENT.find(a("bazz")) == null &&
!STUDENT.findPrefix(a("boor")) && !STUDENT.findPrefix(a("z")) ? 1 : 0;
}
public static int testFindingNullEntriesCausesError() {
try {
STUDENT.find(null);
return 0;
} catch (IllegalArgumentException ex) {
// Do nothing
}
try {
STUDENT.findPrefix(null);
return 0;
} catch (IllegalArgumentException ex) {
// Do nothing
}
return 1;
}
/**
* Tests that inserts correctly wipe out old values.
*/
public static int testInsertReplacesOldValue() {
AlphabeticString key = a("myKey");
boolean initialValueIsNull = STUDENT.insert(key, "foo") == null;
boolean originalValueReturned = STUDENT.insert(key, "bar").equals("foo");
boolean replacementValueReturned = STUDENT.insert(key, "baz").equals("bar");
return initialValueIsNull && originalValueReturned && replacementValueReturned ? 1 : 0;
}
public static int testInsertingNullEntriesCausesError() {
try {
STUDENT.insert(null, "foo");
return 0;
} catch (IllegalArgumentException ex) {
// Do nothing
}
try {
STUDENT.insert(a("foo"), null);
return 0;
} catch (IllegalArgumentException ex) {
// Do nothing
}
return 1;
}
/**
* Checks to see the trie correctly handles the case where you delete
* absolutely everything.
*/
public static int testDeleteAll() {
AlphabeticString keyA = a("keyboard");
AlphabeticString keyB = a("keyesian");
AlphabeticString keyC = a("bayesian");
if (STUDENT.size() != 0 || !STUDENT.isEmpty()) {
return 0;
}
STUDENT.insert(keyA, "KEYBOARD");
STUDENT.insert(keyB, "KEYESIAN");
STUDENT.insert(keyC, "BAYESIAN");
if (!containsAllPaths(STUDENT, "keyboard", "keyesian", "bayesian")) {
return 0;
}
if (STUDENT.size() != 3 || STUDENT.isEmpty()) {
return 0;
}
STUDENT.delete(keyA);
STUDENT.delete(keyB);
STUDENT.delete(keyC);
if (STUDENT.size() != 0 || !STUDENT.isEmpty()) {
return 0;
}
return doesNotContainAll(STUDENT, "keyboard", "keyesian", "bayesian") ? 1 : 0;
}
/**
* Tests what happens if you attempt deleting something that doesn't exist
* in the trie (but _does_ partially overlap).
*/
public static int testDeleteNothing() {
STUDENT.insert(a("aaaa"), "foo");
if (!containsPath(STUDENT, "aaaa", "foo") || STUDENT.size() != 1 || STUDENT.isEmpty()) {
return 0;
}
// Should not change the trie
STUDENT.delete(a("aa"));
STUDENT.delete(a("a"));
STUDENT.delete(a("abc"));
STUDENT.delete(a("aaaaa"));
STUDENT.delete(a(""));
STUDENT.delete(a("foobar"));
if (!containsPath(STUDENT, "aaaa", "foo") || STUDENT.size() != 1 || STUDENT.isEmpty()) {
return 0;
}
return 1;
}
/**
* Tests what happens if you try deleting and inserting single characters
*/
public static int testDeleteAndInsertSingleChars() {
STUDENT.insert(a("a"), "A");
STUDENT.insert(a("b"), "B");
STUDENT.delete(a("a"));
STUDENT.insert(a("b"), "BB");
MockNode expected = node()
.branch('b', node("BB"));
return equals(expected, getField(STUDENT, "root")) ? 1 : 0;
}
/**
* Tests to see if HashTrieMap correctly handles a trie where everything is in a straight
* line/the trie has no branching.
*/
public static int testDeleteWorksWhenTrieHasNoBranches() {
AlphabeticString keyA = a("ghost");
AlphabeticString keyB = a("gh");
STUDENT.insert(keyA, "A");
STUDENT.insert(keyB, "B");
// Trie should still contain "ghost -> A"
STUDENT.delete(keyB);
if (STUDENT.find(keyB) != null || !STUDENT.findPrefix(keyB) || !STUDENT.find(keyA).equals("A")) {
return 0;
}
// Trie should now contain "gh -> C", but not "ghost -> A"
STUDENT.insert(keyB, "C");
STUDENT.delete(keyA);
return (STUDENT.find(keyB).equals("C") && STUDENT.find(keyA) == null && !STUDENT.findPrefix(a("gho"))) ? 1 : 0;
}
/**
* A slight variation of the previous test.
*/
public static int testDeletingAtRoot() {
STUDENT.insert(a(""), "foo");
STUDENT.insert(a("a"), "bar");
STUDENT.delete(a("a"));
STUDENT.insert(a("b"), "baz");
if (STUDENT.find(a("a")) != null) {
return 0;
}
if (!"foo".equals(STUDENT.find(a("")))) {
return 0;
}
if (!"baz".equals(STUDENT.find(a("b")))) {
return 0;
}
MockNode expected = new MockNode("foo")
.branch('b', new MockNode("baz"));
return equals(expected, getField(STUDENT, "root")) ? 1 : 0;
}
/**
* Tests that just working with empty strings does the correct thing.
*/
public static int testDeletingEmptyString() {
STUDENT.insert(a(""), "Foo");
if (!"Foo".equals(STUDENT.find(a(""))) || STUDENT.size() != 1 || STUDENT.isEmpty()) {
return 0;
}
STUDENT.delete(a(""));
if (STUDENT.find(a("")) != null || STUDENT.size() > 0 && !STUDENT.isEmpty()) {
return 0;
}
STUDENT.insert(a(""), "Bar");
return "Bar".equals(STUDENT.find(a(""))) && STUDENT.size() == 1 && !STUDENT.isEmpty() ? 1 : 0;
}
public static int testDeletingNullEntriesCausesError() {
try {
STUDENT.delete((AlphabeticString) null);
} catch (IllegalArgumentException ex) {
return 1;
}
return 0;
}
public static int testClear() {
addAll(STUDENT, "keyboard", "keyesian", "bayesian");
STUDENT.clear();
return (STUDENT.size() == 0 &&
STUDENT.isEmpty() &&
doesNotContainAll(STUDENT, "keyboard", "keyesian", "bayesian")) ? 1 : 0;
}
public static int checkUnderlyingStructure() {
STUDENT.insert(a(""), "A");
STUDENT.insert(a("foo"), "B");
STUDENT.insert(a("fez"), "C");
STUDENT.insert(a("fezzy"), "D");
STUDENT.insert(a("jazz"), "E");
STUDENT.insert(a("jazzy"), "F");
MockNode fullExpected = node("A")
.branch('f', node()
.branch('o', node()
.branch('o', node("B")))
.branch('e', node()
.branch('z', node("C")
.branch('z', node()
.branch('y', node("D"))))))
.branch('j', node()
.branch('a', node()
.branch('z', node()
.branch('z', node("E")
.branch('y', node("F"))))));
if (!equals(fullExpected, getField(STUDENT, "root"))) {
return 0;
}
STUDENT.delete(a("fezzy"));
STUDENT.delete(a("jazz"));
MockNode delete1 = node("A")
.branch('f', node()
.branch('o', node()
.branch('o', node("B")))
.branch('e', node()
.branch('z', node("C"))))
.branch('j', node()
.branch('a', node()
.branch('z', node()
.branch('z', node()
.branch('y', node("F"))))));
if (!equals(delete1, getField(STUDENT, "root"))) {
return 0;
}
STUDENT.delete(a(""));
STUDENT.delete(a("foo"));
STUDENT.delete(a("jazz")); // should do nothing
MockNode delete2 = node()
.branch('f', node()
.branch('e', node()
.branch('z', node("C"))))
.branch('j', node()
.branch('a', node()
.branch('z', node()
.branch('z', node()
.branch('y', node("F"))))));
if (!equals(delete2, getField(STUDENT, "root"))) {
return 0;
}
STUDENT.insert(a("f"), "Z");
STUDENT.delete(a("jazzy"));
STUDENT.delete(a("fez"));
MockNode delete3 = node().branch('f', node("Z"));
if (!equals(delete3, getField(STUDENT, "root"))) {
return 0;
}
STUDENT.delete(a("f"));
boolean rootIsSingleNode = equals(node(), getField(STUDENT, "root"));
boolean rootIsNull = equals(null, getField(STUDENT, "root"));
if (!(rootIsSingleNode || rootIsNull)) {
return 0;
}
return 1;
}
protected static boolean equals(MockNode expected, HashTrieMap<Character, AlphabeticString, String>.HashTrieNode student) {
if (expected == null && student == null) {
return true;
} else if (expected == null || student == null) {
// If only one of the two is null
return false;
} else if (expected.value != null && !expected.value.equals(student.value)) {
// If values don't match
return false;
} else if (expected.value == null && student.value != null) {
// If only one of the values are null
return false;
} else if (expected.pointers.size() != student.pointers.size()) {
// If number of pointers is not the same
return false;
} else {
// If student doesn't contain the given char, 'equals' will fail one level down
// in one of the base cases
for (char c : expected.pointers.keySet()) {
boolean result = equals(expected.pointers.get(c), student.pointers.get(c));
if (!result) {
return false;
}
}
return true;
}
}
protected static MockNode node() {
return new MockNode();
}
protected static MockNode node(String value) {
return new MockNode(value);
}
protected static class MockNode {
public Map<Character, MockNode> pointers;
public String value;
public MockNode() {
this(null);
}
public MockNode(String value) {
this.pointers = new HashMap<>();
this.value = value;
}
public MockNode branch(char c, MockNode child) {
this.pointers.put(c, child);
return this;
}
}
public static int stressTest() {
// Should contain 30 characters
char[] symbols = "abcdefghijklmnopqrstuvwxyz!@#$".toCharArray();
long i = 0;
for (char a : symbols) {
for (char b : symbols) {
for (char c : symbols) {
for (char d : symbols) {
Character[] word = new Character[]{a, b, c, d};
STUDENT.insert(new AlphabeticString(word), "" + i);
i += 1;
}
}
}
}
for (char a : symbols) {
for (char b : symbols) {
if (!STUDENT.findPrefix(new AlphabeticString(new Character[]{a, b}))) {
return 0;
}
}
}
i = 0;
for (char a : symbols) {
for (char b : symbols) {
for (char c : symbols) {
for (char d : symbols) {
Character[] word = new Character[]{a, b, c, d};
if (!STUDENT.find(new AlphabeticString(word)).equals("" + i)) {
return 0;
}
i += 1;
}
}
}
}
return 1;
}
/**
* Converts a String into an AlphabeticString
*/
private static AlphabeticString a(String s) {
return new AlphabeticString(s);
}
/**
* Checks if the trie contains the word and the expected value, and that all prefixes of
* the word exist in the trie.
*/
private static boolean containsPath(HashTrieMap<Character, AlphabeticString, String> trie, String word, String expectedValue) {
AlphabeticString key = a(word);
boolean valueCorrect = expectedValue.equals(trie.find(key));
boolean fullWordIsPrefix = trie.findPrefix(key);
boolean invalidWordDoesNotExist = trie.find(a(word + "$")) == null;
if (!valueCorrect || !fullWordIsPrefix || !invalidWordDoesNotExist) {
return false;
}
return allPrefixesExist(trie, word);
}
/**
* Checks if the trie contains the word, and that all prefixes of the word exist in the trie.
*
* Assumes that the expected value is word.toUpperCase().
*/
private static boolean containsPath(HashTrieMap<Character, AlphabeticString, String> trie, String word) {
return containsPath(trie, word, word.toUpperCase());
}
/**
* Returns true if all prefixes of a word exist in the trie.
*
* That is, if we do `trie.insert(new AlphabeticString("dog"), "some-value")`, this method
* would check to see if "dog", "do", "d", and "" are all prefixes of the trie.
*/
private static boolean allPrefixesExist(HashTrieMap<Character, AlphabeticString, String> trie, String word) {
String accum = "";
for (char c : word.toCharArray()) {
accum += c;
if (!trie.findPrefix(a(accum))) {
return false;
}
}
return true;
}
private static boolean containsAllPaths(HashTrieMap<Character, AlphabeticString, String> trie, String... words) {
for (String word : words) {
if (!containsPath(trie, word)) {
return false;
}
}
return true;
}
private static boolean doesNotContainAll(HashTrieMap<Character, AlphabeticString, String> trie, String... words) {
for (String word : words) {
if (trie.find(a(word)) != null) {
return false;
}
}
return true;
}
private static boolean containsAllPrefixes(HashTrieMap<Character, AlphabeticString, String> trie, String... words) {
for (String word : words) {
if (!trie.findPrefix(a(word))) {
return false;
}
}
return true;
}
private static boolean doesNotContainAllPrefixes(HashTrieMap<Character, AlphabeticString, String> trie, String... words) {
for (String word : words) {
if (trie.findPrefix(a(word))) {
return false;
}
}
return true;
}
private static void addAll(HashTrieMap<Character, AlphabeticString, String> trie, String... words) {
for (String word : words) {
trie.insert(a(word), word.toUpperCase());
}
}
}
package tests.gitlab.ckpt2;
import p2.sorts.HeapSort;
import tests.TestsUtility;
public class HeapSortTests extends TestsUtility {
public static void main(String[] args) {
new HeapSortTests().run();
}
@Override
protected void run() {
SHOW_TESTS = true;
test("integer_sorted");
test("integer_random");
finish();
}
public static int integer_sorted() {
Integer[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Integer[] arr_sorted = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
HeapSort.sort(arr, (i1, i2) -> i1.compareTo(i2));
for(int i = 0; i < arr.length; i++) {
if(!arr[i].equals(arr_sorted[i]))
return 0;
}
return 1;
}
public static int integer_random() {
Integer[] arr = {3, 1, 4, 5, 9, 2, 6, 7, 8};
Integer[] arr_sorted = {1, 2, 3, 4, 5, 6, 7, 8, 9};
HeapSort.sort(arr, (i1, i2) -> i1.compareTo(i2));
for(int i = 0; i < arr.length; i++) {
if(!arr[i].equals(arr_sorted[i]))
return 0;
}
return 1;
}
}