From c95c98764a9f2a469da7367c1eac54ffbe9312b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ing=2E=20Radom=C3=ADr=20Pol=C3=A1ch?= <polacrad@fit.cvut.cz>
Date: Sun, 14 Sep 2014 22:44:47 +0200
Subject: [PATCH] FEATURE: cylcic string comparison

---
 .../compare/string/CyclicStringCompare.cpp    | 41 +++++++++++++++++++
 .../src/compare/string/CyclicStringCompare.h  | 24 +++++++++++
 alib2algo/test-src/compare/compareTest.cpp    | 33 +++++++++++++++
 alib2algo/test-src/compare/compareTest.h      | 21 ++++++++++
 alib2data/src/string/CyclicString.cpp         | 11 +++++
 alib2data/src/string/CyclicString.h           |  1 +
 alib2data/src/string/LinearString.cpp         | 11 +++++
 alib2data/src/string/LinearString.h           |  1 +
 alib2data/src/string/StringBase.h             |  2 +-
 .../src/string/common/StringAlphabet.cpp      |  6 +++
 alib2data/src/string/common/StringAlphabet.h  |  8 +++-
 11 files changed, 156 insertions(+), 3 deletions(-)
 create mode 100644 alib2algo/src/compare/string/CyclicStringCompare.cpp
 create mode 100644 alib2algo/src/compare/string/CyclicStringCompare.h
 create mode 100644 alib2algo/test-src/compare/compareTest.cpp
 create mode 100644 alib2algo/test-src/compare/compareTest.h

diff --git a/alib2algo/src/compare/string/CyclicStringCompare.cpp b/alib2algo/src/compare/string/CyclicStringCompare.cpp
new file mode 100644
index 0000000000..9c15baa629
--- /dev/null
+++ b/alib2algo/src/compare/string/CyclicStringCompare.cpp
@@ -0,0 +1,41 @@
+/*
+ * CyclicStringCompare.cpp
+ *
+ *  Created on: Oct 9, 2014
+ *      Author: Radomír Polcáh */
+
+#include "CyclicStringCompare.h"
+
+namespace compare {
+	
+bool CyclicStringCompare::equals(const string::LinearString& u, const string::LinearString& v) {
+    int n = (int)u.getContent().size();
+    int i = -1, j = -1, k;
+    if (n != v.getContent().size()) return false;
+
+    while(i < n - 1 && j < n - 1)
+    {
+        k = 1;
+        while(k <= n && u.getContent()[(i + k) % n] == v.getContent()[(j + k) % n]) k++;
+        if (k > n) return true;
+        if (u.getContent()[(i + k) % n] > v.getContent()[(j + k) % n]) i += k; else j += k;
+    }
+    return false;
+}
+
+int CyclicStringCompare::compare(const string::LinearString& u, const string::LinearString& v) {
+    int n = (int)u.getContent().size(), m = (int)v.getContent().size();
+    int i = -1, j = -1, k;
+
+    bool last = 0;
+    while(i < n - 1 && j < m - 1)
+    {
+        k = 1;
+        while(k <= n && u.getContent()[(i + k) % n] == v.getContent()[(j + k) % m]) k++;
+        if (k > n) return 0;
+        if (last = u.getContent()[(i + k) % n] > v.getContent()[(j + k) % m]) i += k; else j += k;
+    }
+    return last ? 1 : - 1;
+}
+
+}
diff --git a/alib2algo/src/compare/string/CyclicStringCompare.h b/alib2algo/src/compare/string/CyclicStringCompare.h
new file mode 100644
index 0000000000..5b8cb14518
--- /dev/null
+++ b/alib2algo/src/compare/string/CyclicStringCompare.h
@@ -0,0 +1,24 @@
+/*
+ * CyclicStringCompare.h
+ *
+ *  Created on: Oct 14, 2014
+ *      Author: Radomír Polách
+ */
+
+#ifndef CYCLIC_STRING_COMPARE_H_
+#define CYCLIC_STRING_COMPARE_H_
+
+#include "string/LinearString.h" 
+
+namespace compare {
+
+class CyclicStringCompare {
+public:
+	static bool equals(const string::LinearString& u, const string::LinearString& v);
+	static int compare(const string::LinearString& u, const string::LinearString& v);
+
+};
+
+}
+
+#endif /* CYCLIC_STRING_COMPARE_H_ */
diff --git a/alib2algo/test-src/compare/compareTest.cpp b/alib2algo/test-src/compare/compareTest.cpp
new file mode 100644
index 0000000000..9ada8b24b7
--- /dev/null
+++ b/alib2algo/test-src/compare/compareTest.cpp
@@ -0,0 +1,33 @@
+#include <list>
+#include "compareTest.h"
+
+#include "compare/string/CyclicStringCompare.h"
+#include "string/LinearString.h"
+
+#define CPPUNIT_IMPLY(x, y) CPPUNIT_ASSERT(!(x) || (y))
+
+CPPUNIT_TEST_SUITE_REGISTRATION( compareTest );
+
+void compareTest::setUp() {
+}
+
+void compareTest::tearDown() {
+}
+
+void compareTest::testCyclicStringCompareBoolean() {
+  string::LinearString str1("alfa");
+  string::LinearString str2("aalf");
+  str2.addSymbolsToAlphabet(str1.getAlphabet());
+  str1.addSymbolsToAlphabet(str2.getAlphabet());
+  
+  CPPUNIT_ASSERT(compare::CyclicStringCompare::equals(str1, str2));
+}
+
+void compareTest::testCyclicStringCompareInt() {
+  string::LinearString str1("alfa");
+  string::LinearString str2("aalf");
+  str2.addSymbolsToAlphabet(str1.getAlphabet());
+  str1.addSymbolsToAlphabet(str2.getAlphabet());
+  
+  CPPUNIT_ASSERT(compare::CyclicStringCompare::compare(str1, str2) == 0);
+}
diff --git a/alib2algo/test-src/compare/compareTest.h b/alib2algo/test-src/compare/compareTest.h
new file mode 100644
index 0000000000..9238a15e2b
--- /dev/null
+++ b/alib2algo/test-src/compare/compareTest.h
@@ -0,0 +1,21 @@
+#ifndef COMPARE_TEST_H_
+#define COMPARE_TEST_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class compareTest : public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE( compareTest );
+  CPPUNIT_TEST( testCyclicStringCompareBoolean );
+  CPPUNIT_TEST( testCyclicStringCompareInt );
+  CPPUNIT_TEST_SUITE_END();
+
+public:
+  void setUp();
+  void tearDown();
+
+  void testCyclicStringCompareBoolean();
+  void testCyclicStringCompareInt();
+};
+
+#endif  // COMPARE_TEST_H_
diff --git a/alib2data/src/string/CyclicString.cpp b/alib2data/src/string/CyclicString.cpp
index fcf1fc8e58..a0903dca5b 100644
--- a/alib2data/src/string/CyclicString.cpp
+++ b/alib2data/src/string/CyclicString.cpp
@@ -7,6 +7,9 @@
 
 #include "CyclicString.h"
 #include "../exception/AlibException.h"
+#include "../label/Label.h"
+#include "../label/CharacterLabel.h"
+#include "../alphabet/LabeledSymbol.h"
 
 #include <cassert>
 #include <sstream>
@@ -43,6 +46,14 @@ CyclicString::CyclicString(std::vector<alphabet::Symbol>&& data) {
 	setContent(std::move(data));
 }
 
+CyclicString::CyclicString(const std::string& str) {
+    for (unsigned i = 0; i < str.length(); ++i)
+    {
+        m_Data.push_back(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::CharacterLabel(str[i])))));    
+    }
+    alphabet = std::set<alphabet::Symbol>(m_Data.begin(), m_Data.end());
+}
+
 StringBase* CyclicString::clone() const {
 	return new CyclicString(*this);
 }
diff --git a/alib2data/src/string/CyclicString.h b/alib2data/src/string/CyclicString.h
index c1b4aef344..7173b9790d 100644
--- a/alib2data/src/string/CyclicString.h
+++ b/alib2data/src/string/CyclicString.h
@@ -31,6 +31,7 @@ public:
 	explicit CyclicString(std::set<alphabet::Symbol>&& alphabet, std::vector<alphabet::Symbol>&& data);
 	explicit CyclicString(const std::vector<alphabet::Symbol>& data);
 	explicit CyclicString(std::vector<alphabet::Symbol>&& data);
+    explicit CyclicString(const std::string& str);
 
 	virtual StringBase* clone() const;
 	virtual StringBase* plunder() &&;
diff --git a/alib2data/src/string/LinearString.cpp b/alib2data/src/string/LinearString.cpp
index 4c875addc9..71daea259d 100644
--- a/alib2data/src/string/LinearString.cpp
+++ b/alib2data/src/string/LinearString.cpp
@@ -7,6 +7,9 @@
 
 #include "LinearString.h"
 #include "../exception/AlibException.h"
+#include "../label/Label.h"
+#include "../label/CharacterLabel.h"
+#include "../alphabet/LabeledSymbol.h"
 
 #include <cassert>
 #include <sstream>
@@ -43,6 +46,14 @@ LinearString::LinearString(std::vector<alphabet::Symbol>&& data) {
 	m_Data = std::move(data);
 }
 
+LinearString::LinearString(const std::string& str) {
+    for (unsigned i = 0; i < str.length(); ++i)
+    {
+        m_Data.push_back(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::CharacterLabel(str[i])))));    
+    }
+    alphabet = std::set<alphabet::Symbol>(m_Data.begin(), m_Data.end());
+}
+
 StringBase* LinearString::clone() const {
 	return new LinearString(*this);
 }
diff --git a/alib2data/src/string/LinearString.h b/alib2data/src/string/LinearString.h
index 875ca997a2..53580f6279 100644
--- a/alib2data/src/string/LinearString.h
+++ b/alib2data/src/string/LinearString.h
@@ -32,6 +32,7 @@ public:
 	explicit LinearString(std::set<alphabet::Symbol>&& alphabet, std::vector<alphabet::Symbol>&& data);
 	explicit LinearString(const std::vector<alphabet::Symbol>& data);
 	explicit LinearString(std::vector<alphabet::Symbol>&& data);
+    explicit LinearString(const std::string& str);
 
 	virtual StringBase* clone() const;
 	virtual StringBase* plunder() &&;
diff --git a/alib2data/src/string/StringBase.h b/alib2data/src/string/StringBase.h
index 2ac457525e..64ef5419e6 100644
--- a/alib2data/src/string/StringBase.h
+++ b/alib2data/src/string/StringBase.h
@@ -27,7 +27,7 @@ public:
 
 	virtual StringBase* clone() const = 0;
 	virtual StringBase* plunder() && = 0;
-
+    
 };
 
 } /* namespace string */
diff --git a/alib2data/src/string/common/StringAlphabet.cpp b/alib2data/src/string/common/StringAlphabet.cpp
index 4b81ba221b..22c34a2203 100644
--- a/alib2data/src/string/common/StringAlphabet.cpp
+++ b/alib2data/src/string/common/StringAlphabet.cpp
@@ -19,6 +19,12 @@ bool StringAlphabet::addSymbolToAlphabet(const alphabet::Symbol& symbol) {
 	return alphabet.insert(symbol).second;
 }
 
+void StringAlphabet::addSymbolsToAlphabet(const std::set<alphabet::Symbol>& symbols) {
+	for(const alphabet::Symbol& addedSymbol : symbols) {
+		addSymbolToAlphabet(addedSymbol);
+	}
+}
+
 void StringAlphabet::setAlphabet(const std::set<alphabet::Symbol>& newSymbols) {
 	std::set<alphabet::Symbol> removed;
 	std::set_difference(alphabet.begin(), alphabet.end(), newSymbols.begin(), newSymbols.end(), std::inserter(removed, removed.end()));
diff --git a/alib2data/src/string/common/StringAlphabet.h b/alib2data/src/string/common/StringAlphabet.h
index a4c0365d65..5838ed4608 100644
--- a/alib2data/src/string/common/StringAlphabet.h
+++ b/alib2data/src/string/common/StringAlphabet.h
@@ -24,14 +24,18 @@ public:
 	/**
 	 * Adds input symbol to input alphabet.
 	 * @param symbol Symbol to add
-	 * @throws AutomatonException when symbol already exists
 	 */
 	bool addSymbolToAlphabet(const alphabet::Symbol& symbol);
+	
+    /**
+	 * Adds input symbols to input alphabet.
+	 * @param symbols Symbol to add
+	 */
+	void addSymbolsToAlphabet(const std::set<alphabet::Symbol>& symbols);
 
 	/**
 	 * Sets input symbols of the string.
 	 * @param symbols Symbols to set
-	 * @throws AutomatonException when symbol already exists
 	 */
 	void setAlphabet(const std::set<alphabet::Symbol>& symbols);
 
-- 
GitLab