commit a2ce29bf44d38d42b7f6955915420827a92d6eca Author: RinRi Date: Wed May 18 18:51:11 2022 +0600 initial commit diff --git a/FSA.java b/FSA.java new file mode 100644 index 0000000..ade377a --- /dev/null +++ b/FSA.java @@ -0,0 +1,196 @@ +import java.io.*; +import java.lang.*; +import java.util.*; + +class Edge { + public int s, a; + Edge(int s, int a) { + this.s = s; + this.a = a; + } + + public String toString() { + return this.s + ", " + this.a; + } +} + +class FSM { + private ArrayList states, alpha, finalState, transitions, warnings; + private String initialState; + private Integer initialStateID; + private ArrayList> tr; + private ArrayList> tr2way; + private HashMap stateToInt, alphaToInt; + private HashSet isFinal; + private FileWriter out; + private Integer szs, sza; + private Boolean used[]; + + public void error(String msg) throws IOException { + out.write("Error:\n" + msg); + out.close(); + System.exit(0); + } + + int dfs(int v) { + int ans = 1, n = tr.get(v).size(); + used[v] = true; + + for (int i = 0; i < n; ++i) { + int to = tr.get(v).get(i).s; + if (!used[to]) + ans += dfs(to); + } + + return ans; + } + + void dfs2way(int v) { + used[v] = true; + int n = tr2way.get(v).size(); + + for (int i = 0; i < n; ++i) { + int to = tr2way.get(v).get(i).s; + if (!used[to]) + dfs2way(to); + } + } + + FSM(String states, String alpha, String initialState, String finalState, String transitions, + FileWriter out) + throws IOException { + this.out = out; + if (!states.matches("states=\\[.*\\]$") || !alpha.matches("alpha=\\[.*\\]$") + || !initialState.matches("init\\.st=\\[.*\\]$") + || !finalState.matches("fin\\.st=\\[.*\\]$") || !transitions.matches("trans=\\[.*\\]$")) + error("E5: Input file is malformed"); + + this.states = new ArrayList(Arrays.asList(states.split("states=\\[|,|\\]"))); + this.alpha = new ArrayList(Arrays.asList(alpha.split("alpha=\\[|,|\\]"))); + String[] temp = initialState.split("init\\.st=\\[|\\]"); + if (temp.length <= 1) + error("E4: Initial state is not defined"); + this.initialState = temp[1]; + this.finalState = + new ArrayList(Arrays.asList(finalState.split("fin\\.st=\\[|,|\\]"))); + this.transitions = + new ArrayList(Arrays.asList(transitions.split("trans=\\[|,|\\]"))); + + this.szs = this.states.size(); + this.sza = this.alpha.size(); + + stateToInt = new HashMap(); + alphaToInt = new HashMap(); + isFinal = new HashSet(); + tr = new ArrayList>(); + tr2way = new ArrayList>(); + for (int i = 0; i < this.states.size(); ++i) { + tr.add(new ArrayList()); + tr2way.add(new ArrayList()); + } + warnings = new ArrayList(); + used = new Boolean[szs]; + + for (int i = 1; i < szs; ++i) this.stateToInt.put(this.states.get(i), i); + + if (this.finalState.size() <= 1) + warnings.add("W1: Accepting state is not defined"); + + for (int i = 1; i < this.finalState.size(); ++i) { + if (this.stateToInt.containsKey(this.finalState.get(i))) + isFinal.add(i); + else + error("E1: A state '" + this.finalState.get(i) + "' is not in the set of states"); + } + + for (int i = 1; i < sza; ++i) alphaToInt.put(this.alpha.get(i), i); + + for (int i = 1; i < this.transitions.size(); ++i) { + String[] cur = this.transitions.get(i).split(">"); + + if (cur.length != 3) + error("E5: Input file is malformed"); + + if (!this.stateToInt.containsKey(cur[0])) + error("E1: A state '" + cur[0] + "' is not in the set of states"); + + if (!this.alphaToInt.containsKey(cur[1])) + error("E3: A transition '" + cur[1] + "' is not represented in the alphabet"); + + if (!this.stateToInt.containsKey(cur[2])) + error("E1: A state '" + cur[2] + "' is not in the set of states"); + + int l = stateToInt.get(cur[0]), m = alphaToInt.get(cur[1]), r = stateToInt.get(cur[2]); + tr.get(l).add(new Edge(r, m)); + tr2way.get(l).add(new Edge(r, m)); + tr2way.get(r).add(new Edge(l, m)); + } + + if (stateToInt.containsKey(this.initialState)) + initialStateID = stateToInt.get(this.initialState); + else + error("E4: Initial state is not defined"); + + int components = 0; + for (int i = 1; i < szs; ++i) used[i] = false; + for (int i = 1; i < szs; ++i) { + if (!used[i]) { + dfs2way(i); + components++; + } + } + + if (components > 1) + error("E2: Some states are disjoint"); + + for (int i = 1; i < szs; ++i) used[i] = false; + + int cnt = dfs(initialStateID); + if (cnt != szs - 1) + warnings.add("W2: Some states are not reachable from the initial state"); + + Boolean isDet = true, isComplete = true; + for (int i = 1; i < szs; ++i) { + HashSet st = new HashSet(); + for (int j = 0; j < tr.get(i).size(); ++j) { + int a = tr.get(i).get(j).a; + if (st.contains(a)) + isDet = false; + else + st.add(a); + } + if (st.size() != this.alpha.size() - 1) + isComplete = false; + } + if (!isDet) + warnings.add("W3: FSA is nondeterministic"); + + if (isComplete) + out.write("FSA is complete"); + else + out.write("FSA is incomplete"); + + if (warnings.size() > 0) + out.write("\nWarning: "); + for (int i = 0; i < warnings.size(); ++i) { + out.write("\n" + warnings.get(i)); + } + + out.close(); + } +} + +public class FSA { + public static void main(String[] args) throws IOException { + FileReader inp = new FileReader("fsa.txt"); + FileWriter out = new FileWriter("result.txt"); + Scanner in = new Scanner(inp); + + String states = in.nextLine(); + String alpha = in.nextLine(); + String initialState = in.nextLine(); + String finalState = in.nextLine(); + String transitions = in.nextLine(); + FSM fsm = new FSM(states, alpha, initialState, finalState, transitions, out); + } +} diff --git a/FSAtoREGEX.java b/FSAtoREGEX.java new file mode 100644 index 0000000..e7debaf --- /dev/null +++ b/FSAtoREGEX.java @@ -0,0 +1,257 @@ +import java.io.*; +import java.lang.*; +import java.util.*; + +class Edge { + public int s, a; + Edge(int s, int a) { + this.s = s; + this.a = a; + } + + public String toString() { + return this.s + ", " + this.a; + } +} + +class FSM { + private ArrayList states, alpha, finalState, transitions; + private String initialState; + private Integer initialStateID; + private ArrayList> tr; + private ArrayList> tr2way; + private HashMap stateToInt, alphaToInt; + private HashSet isFinal; + private FileWriter out; + private Integer szs, sza; + private Boolean used[]; + private ArrayList>> r; + + public void error(String msg) throws IOException { + out.write("Error:\n" + msg); + out.close(); + System.exit(0); + } + + int dfs(int v) { + int ans = 1, n = tr.get(v).size(); + used[v] = true; + + for (int i = 0; i < n; ++i) { + int to = tr.get(v).get(i).s; + if (!used[to]) + ans += dfs(to); + } + + return ans; + } + + void dfs2way(int v) { + used[v] = true; + int n = tr2way.get(v).size(); + + for (int i = 0; i < n; ++i) { + int to = tr2way.get(v).get(i).s; + if (!used[to]) + dfs2way(to); + } + } + + FSM(String states, String alpha, String initialState, String finalState, String transitions, + FileWriter out) + throws IOException { + this.out = out; + // validate input + if (!states.matches("states=\\[.*\\]$") || !alpha.matches("alpha=\\[.*\\]$") + || !initialState.matches("initial=\\[.*\\]$") + || !finalState.matches("accepting=\\[.*\\]$") + || !transitions.matches("trans=\\[.*\\]$")) + error("E0: Input file is malformed"); + + this.states = new ArrayList(Arrays.asList(states.split("states=\\[|,|\\]"))); + this.alpha = new ArrayList(Arrays.asList(alpha.split("alpha=\\[|,|\\]"))); + this.finalState = + new ArrayList(Arrays.asList(finalState.split("accepting=\\[|,|\\]"))); + this.transitions = + new ArrayList(Arrays.asList(transitions.split("trans=\\[|,|\\]"))); + + // initialization + this.szs = this.states.size() - 1; + this.sza = this.alpha.size() - 1; + if (szs <= 0 || sza <= 0) { + error("E0: Input file is malformed"); + } + + stateToInt = new HashMap(); + alphaToInt = new HashMap(); + isFinal = new HashSet(); + tr = new ArrayList>(); + tr2way = new ArrayList>(); + for (int i = 0; i < szs; ++i) { + tr.add(new ArrayList()); + tr2way.add(new ArrayList()); + } + used = new Boolean[szs]; + + // initialize R[k][i][j]; 0 <= k <= n; 0 <= i, j < n; + r = new ArrayList>>(); + for (int k = 0; k < szs + 1; k++) { + r.add(new ArrayList>()); + for (int i = 0; i < szs; ++i) { + r.get(k).add(new ArrayList()); + for (int j = 0; j < szs; ++j) { + r.get(k).get(i).add(new String()); + } + } + } + + // create a graph with nodes starting from 0 + for (int i = 1; i <= szs; ++i) this.stateToInt.put(this.states.get(i), i - 1); + + // validate transitions + for (int i = 1; i < this.transitions.size(); ++i) { + String[] cur = this.transitions.get(i).split(">"); + + if (cur.length != 3) + error("E0: Input file is malformed"); + } + + for (int i = 1; i < this.finalState.size(); ++i) { + if (this.stateToInt.containsKey(this.finalState.get(i))) + isFinal.add(this.stateToInt.get(this.finalState.get(i))); + else + error("E1: A state '" + this.finalState.get(i) + "' is not in the set of states"); + } + + for (int i = 1; i <= sza; ++i) alphaToInt.put(this.alpha.get(i), i - 1); + + for (int i = 1; i < this.transitions.size(); ++i) { + String[] cur = this.transitions.get(i).split(">"); + + if (cur.length != 3) + error("E0: Input file is malformed"); + + if (!this.stateToInt.containsKey(cur[0])) + error("E1: A state '" + cur[0] + "' is not in the set of states"); + + if (!this.stateToInt.containsKey(cur[2])) + error("E1: A state '" + cur[2] + "' is not in the set of states"); + + if (!this.alphaToInt.containsKey(cur[1])) + error("E3: A transition '" + cur[1] + "' is not represented in the alphabet"); + + int l = stateToInt.get(cur[0]), m = alphaToInt.get(cur[1]), r = stateToInt.get(cur[2]); + tr.get(l).add(new Edge(r, m)); + tr2way.get(l).add(new Edge(r, m)); + tr2way.get(r).add(new Edge(l, m)); + } + + int components = 0; + for (int i = 0; i < szs; ++i) used[i] = false; + for (int i = 0; i < szs; ++i) { + if (!used[i]) { + dfs2way(i); + components++; + } + } + + if (components > 1) + error("E2: Some states are disjoint"); + + for (int i = 0; i < szs; ++i) used[i] = false; + + String[] temp = initialState.split("initial=\\[|\\]"); + if (temp.length <= 1) + error("E4: Initial state is not defined"); + this.initialState = temp[1]; + + if (stateToInt.containsKey(this.initialState)) + initialStateID = stateToInt.get(this.initialState); + else + error("E1: A state '" + this.initialState + "' is not in the set of states"); + + Boolean isDet = true, isComplete = true; + for (int i = 0; i < szs; ++i) { + HashSet st = new HashSet(); + for (int j = 0; j < tr.get(i).size(); ++j) { + int a = tr.get(i).get(j).a; + if (st.contains(a)) + isDet = false; + else + st.add(a); + } + if (st.size() != sza) + isComplete = false; + } + if (!isDet) + error("E5: FSA is nondeterministic"); + + for (int i = 0; i < szs; ++i) { + for (int j = 0; j < tr.get(i).size(); ++j) { + String curAlpha; + int cur = tr.get(i).get(j).s; + if (r.get(0).get(i).get(cur).isEmpty()) + curAlpha = this.alpha.get(tr.get(i).get(j).a + 1); + else + curAlpha = r.get(0).get(i).get(cur) + "|" + this.alpha.get(tr.get(i).get(j).a + 1); + r.get(0).get(i).set(cur, curAlpha); + } + + for (int j = 0; j < szs; ++j) { + if (i == j) { + String curAlpha; + if (r.get(0).get(i).get(j).isEmpty()) + curAlpha = "eps"; + else + curAlpha = r.get(0).get(i).get(j) + "|eps"; + r.get(0).get(i).set(j, curAlpha); + } else if (r.get(0).get(i).get(j).isEmpty()) { + String curAlpha = "{}"; + r.get(0).get(i).set(j, curAlpha); + } + } + } + + for (int k = 1; k <= szs; ++k) { + for (int i = 0; i < szs; ++i) { + for (int j = 0; j < szs; ++j) { + String cur = "(" + r.get(k-1).get(i).get(k-1) + ")(" + r.get(k-1).get(k-1).get(k-1) + ")*(" + r.get(k-1).get(k-1).get(j) + ")|(" + r.get(k-1).get(i).get(j) + ")"; + r.get(k).get(i).set(j, cur); + } + } + } + + String ans = new String(); + + for (int i = 0; i < szs; ++i) { + if (isFinal.contains(i)) { + if(ans.isEmpty()) + ans = r.get(szs).get(initialStateID).get(i); + else + ans = ans + "|" + r.get(szs).get(initialStateID).get(i); + } + } + + if(ans.isEmpty()) + ans = "{}"; + + out.write(ans); + + out.close(); + } +} + +public class FSAtoREGEX { + public static void main(String[] args) throws IOException { + FileReader inp = new FileReader("input.txt"); + FileWriter out = new FileWriter("output.txt"); + Scanner in = new Scanner(inp); + + String states = in.nextLine(); + String alpha = in.nextLine(); + String initialState = in.nextLine(); + String finalState = in.nextLine(); + String transitions = in.nextLine(); + FSM fsm = new FSM(states, alpha, initialState, finalState, transitions, out); + } +} diff --git a/assignment1dsa/Makefile b/assignment1dsa/Makefile new file mode 100644 index 0000000..b84ce2b --- /dev/null +++ b/assignment1dsa/Makefile @@ -0,0 +1,6 @@ +main: main.cpp + $(CXX) -g -o main -std=c++17 main.cpp + +tester: tester.cpp + $(CXX) -g -o tester -std=c++17 tester.cpp + ./tester > test.txt \ No newline at end of file diff --git a/assignment1dsa/main.cpp b/assignment1dsa/main.cpp new file mode 100644 index 0000000..a1b0b6f --- /dev/null +++ b/assignment1dsa/main.cpp @@ -0,0 +1,632 @@ +#include +#include +#include +#include +#include +#include +#include + +/* + * Amirlan Sharipov BS21-01 + * https://codeforces.com/profile/RinRi + * I've copied most of the comments in this code from the assignment + * specification + */ + +#define PRIMENUM1 1000007 +#define PRIMENUM2 1003337 +#define MAXN 50001 +#define MINN 8 + +using std::chrono::duration; +using std::chrono::duration_cast; +using std::chrono::high_resolution_clock; +using std::chrono::milliseconds; + +template +class ICircularBoundedQueue { + public: + virtual void offer(const T &value) = 0; // insert an element to the rear of + // the queue overwrite the oldest + // elements when the queue is full + + virtual T &poll() = 0; // remove an element from the front of the queue + virtual T &peek() const = 0; // look at the element at the front of the + // queue (without removing it) + virtual void flush() = 0; // remove all elements from the queue + virtual bool isEmpty() const = 0; // is the queue empty? + virtual bool isFull() const = 0; // is the queue full? + virtual int size() const = 0; // number of elements + virtual int capacity() const = 0; // maximum capacity +}; + +template +class ArrayCircularBoundedQueue : ICircularBoundedQueue { + public: + ArrayCircularBoundedQueue(int maxSize) { + mxsz = maxSize; + data = new T *[mxsz](); + } + + ~ArrayCircularBoundedQueue() { + for (int i = 0; i < mxsz; ++i) delete data[i]; + delete[] data; + } + + // time complexity: O(1) in any case + void offer(const T &value) { + if (sz < mxsz) { + curPush = (cur + sz) % mxsz; + sz++; + } + data[curPush++] = new T(value); + curPush %= mxsz; + } + + // time complexity: O(1) in any case + void offer(T *value) { + if (sz < mxsz) { + curPush = (cur + sz) % mxsz; + sz++; + } + data[curPush++] = value; + curPush %= mxsz; + } + + // time complexity: O(1) in any case + T &poll() try { + if (sz == 0) throw "queue is empty!"; + + // T &ans = *data[cur]; + delete data[cur]; + data[cur] = NULL; + sz--; + cur++; + cur %= mxsz; + // return ans; + } catch (const char *msg) { + std::cerr << msg << std::endl; + throw; + } + + // time complexity: O(1) in any case + T *pollpoint() try { + if (sz == 0) throw "queue is empty!"; + + // T &ans = *data[cur]; + data[cur] = NULL; + sz--; + cur++; + cur %= mxsz; + // return ans; + } catch (const char *msg) { + std::cerr << msg << std::endl; + throw; + } + + // time complexity: O(1) in any case + T &peek() const { return *data[cur]; } + + T *peekpoint() const { return data[cur]; } + + // time complexity: O(n) in any case + void flush() { + while (sz) poll(); + } + + // time complexity: O(1) in any case + bool isEmpty() const { return !sz; } + + // time complexity: O(1) in any case + bool isFull() const { return (sz == mxsz); } + + // time complexity: O(1) in any case + int size() const { return sz; } + + // time complexity: O(1) in any case + int capacity() const { return mxsz; } + + // time complexity: O(n) in any case + void print() { + for (int i = 0; i < sz; ++i) { + // data[(cur + i) % mxsz].list(); + std::cout << *data[(cur + i) % mxsz] << '\n'; + } + } + + void printset() { + for (int i = 0; i < sz; ++i) { + data[(cur + i) % mxsz]->list(); + std::cout << '\n'; + } + } + + private: + T **data; + int sz = 0, mxsz = 0, cur = 0, curPush = 0; +}; + +template +class IBoundedStack { + public: + virtual void push(const T &value) = 0; // push an element onto the stack + // remove the oldest element + // when if stack is full + virtual T &pop() = 0; // remove an element from the top of the stack + virtual T &top() const = 0; // look at the element at the top of the stack + // (without removing it) + virtual void flush() = 0; // remove all elements from the stack + virtual bool isEmpty() const = 0; // is the stack empty? + virtual bool isFull() const = 0; // is the stack full? + virtual int size() const = 0; // number of elements + virtual int capacity() const = 0; // maximum capacity +}; + +template +class QueuedBoundedStack : IBoundedStack { + public: + QueuedBoundedStack(int size) { + q1 = new ArrayCircularBoundedQueue(size); + q2 = new ArrayCircularBoundedQueue(size); + mxsz = size; + } + + ~QueuedBoundedStack() { + delete q1; + delete q2; + } + + // time complexity: O(n*m), Theta(n*m). The algorithm's complexity depends + // on the size of q1 as well as the cost of operation of copying. In this + // case(problem C) it is O(n*m), that is why I decided to use pointers + // instead. See function below this one. Worst case O(n), best case O(1), + // avg O(n) + void push(const T &value) { + q2->offer(value); + + while (!q1->isEmpty()) { + if (sz == mxsz && q1->size() == 1) { + q1->poll(); + break; + } + T &temp = q1->peek(); + q2->offer(temp); + q1->poll(); + } + + if (sz < mxsz) sz++; + + ArrayCircularBoundedQueue *temp = q1; + q1 = q2; + q2 = temp; + } + + // time complexity: O(n) + void push(T *value) { + q2->offer(value); + + while (!q1->isEmpty()) { + if (sz == mxsz && q1->size() == 1) { + q1->poll(); + break; + } + T *temp = q1->peekpoint(); + q2->offer(temp); + q1->pollpoint(); + } + + if (sz < mxsz) sz++; + + ArrayCircularBoundedQueue *temp = q1; + q1 = q2; + q2 = temp; + } + + // time complexity: O(1) in any case (theta(1)) + T &pop() try { + if (q1->isEmpty()) throw "q1 is empty!"; + + // T &ans = q1->peek(); + q1->poll(); + sz--; + // return ans; + } catch (const char *msg) { + std::cerr << msg << std::endl; + throw; + } + + // time complexity: O(1) in any case + T &top() const try { + if (q1->isEmpty()) throw "q1 is empty!"; + return q1->peek(); + } catch (const char *msg) { + std::cerr << msg << std::endl; + throw; + } + + // time complexity: O(1) in any case + void flush() { + sz = 0; + q1->flush(); + q2->flush(); + } + + // time complexity: O(1) in any case + bool isEmpty() const { return !sz; } + + // time complexity: O(1) in any case + bool isFull() const { return (sz == mxsz); } + + // time complexity: O(1) in any case + int size() const { return sz; } + + // time complexity: O(1) in any case + int capacity() const { return mxsz; } + + void print() { q1->print(); } + void printset() { q1->printset(); } + + private: + ArrayCircularBoundedQueue *q1, *q2; + int sz = 0, mxsz = 0, cur = 0, curPush = 0; +}; + +template +class ISet { + virtual void add(const T &item) = 0; // add an item to the set + virtual void remove(T &item) = 0; // remove an item from the set + virtual bool contains( + T &item) const = 0; // check if an item belongs to the set + virtual int size() const = 0; // the number of elements in the set + virtual bool isEmpty() const = 0; // check if the set is empty +}; + +template +class DoubleHashSet : ISet { + public: + // TODO: Write comments about every method + + enum State : char { EMPTY = 0, DELETED = 1, TAKEN = 2 }; + + DoubleHashSet() { + sz = 0; + mxsz = 0; + data = 0; + state = 0; + } + + DoubleHashSet(int maxSize) { + mxsz = maxSize; + sz = 0; + data = new T *[mxsz](); + state = new State[mxsz](); + } + + // O(n) because of copying + DoubleHashSet(const DoubleHashSet &st) { + sz = st.size(); + mxsz = st.getMaxSize(); + data = new T *[mxsz](); + state = new State[mxsz](); + T **tempdata = st.getData(); + State *tempstate = st.getState(); + for (int i = 0; i < mxsz; ++i) { + if (tempstate[i] == TAKEN) data[i] = new T(*tempdata[i]); + state[i] = tempstate[i]; + } + } + + // O(n*m) deleting + ~DoubleHashSet() { + for (int i = 0; i < mxsz; ++i) + if (state[i] == TAKEN) delete data[i]; + delete[] data; + delete[] state; + } + + // O(n*m) n -> size, m -> size of data + void list() { + std::ios_base::sync_with_stdio(0); + std::cin.tie(0); + std::cout.tie(0); + + for (int i = 0; i < mxsz; ++i) { + if (state[i] == TAKEN) std::cout << *data[i] << ' '; + } + } + + // Compression function. O(1) + int hash(int h1, int h2, int64_t i) const { + // size_t h1 = hasher(item); + // h1 %= PRIMENUM1; + // size_t h2 = hasher(item); + // h2 %= PRIMENUM2; + return ((int64_t)h1 + i * (int64_t)h2) % (int64_t)mxsz; + // return ((int64_t)hash1(item, PRIMENUM1) + i * (int64_t)hash2(item, + // PRIMENUM2)) % mxsz; return (h1 + i * (int64_t)hash2(item, PRIMENUM2)) + // % mxsz; + } + + // Hash function n1. O(n) + int hash1(const std::string &item, int prime) const { + int ans = 0, sz = item.size(); + int64_t cur = 1; + for (int i = 0; i < item.size(); ++i) { + ans += (cur * (int64_t)item[i]) % prime; + ans %= prime; + cur *= 127; + cur %= prime; + } + return ans; + } + + // Hash function n2. O(n) + int hash2(const std::string &item, int prime) const { + int ans = 0, sz = item.size(); + int64_t cur = 1; + for (int i = 0; i < item.size(); ++i) { + ans += (cur * (int64_t)item[sz - i - 1]) % prime; + ans %= prime; + cur *= 127; + cur %= prime; + } + return ans; + } + + // Add an item to the set O(n^2) in worst case (all colisions). Copying + // takes time as well. Avg and best case: O(n) + void add(const T &item) { + int h1 = hash1(item, PRIMENUM1), h2 = hash2(item, PRIMENUM2); + while (1) { + for (int i = 0; i < mxsz; ++i) { + int pos = hash(h1, h2, i); + if (state[pos] == EMPTY || state[pos] == DELETED) { + data[pos] = new T(item); + state[pos] = TAKEN; + sz++; + return; + } else if (state[pos] == TAKEN) { + if (*data[pos] == item) return; + } + } + + int tempmxsz = mxsz; + T **tempdata = data; + State *tempstate = state; + int newsz = std::max(2 * tempmxsz, 8); + + data = new T *[newsz](); + state = new State[newsz](); + mxsz = newsz; + sz = 0; + + for (int i = 0; i < tempmxsz; ++i) { + if (tempstate[i] == TAKEN) { + add(*tempdata[i]); + } + } + + for (int i = 0; i < tempmxsz; ++i) + if (state[i] == TAKEN) delete tempdata[i]; + delete[] tempdata; + delete[] tempstate; + } + } + + // Remove an item. worst case: O(n*m), avg and best: O(m), where m is size + // of data. + void remove(T &item) try { + int h1 = hash1(item, PRIMENUM1), h2 = hash2(item, PRIMENUM2); + for (int i = 0; i < mxsz; ++i) { + int pos = hash(h1, h2, i); + + if (state[pos] == EMPTY) break; + + if (state[pos] == TAKEN) { + if (*data[pos] == item) { + delete data[pos]; + data[pos] = NULL; + state[pos] = DELETED; + sz--; + return; + } + } + } + + throw "specified item doesn't exist!"; + } catch (const char *msg) { + std::cerr << msg << std::endl; + throw; + } + + // worst case: O(n) + bool contains(T &item) const { + int h1 = hash1(item, PRIMENUM1), h2 = hash2(item, PRIMENUM2); + for (int i = 0; i < mxsz; ++i) { + int pos = hash(h1, h2, i); + + if (state[pos] == EMPTY) break; + + if (state[pos] == TAKEN) + if (*data[pos] == item) return true; + } + return false; + } + + int size() const { return sz; } + + bool isEmpty() const { return (sz == 0); } + + T **getData() const { return data; } + + State *getState() const { return state; } + + int getMaxSize() const { return mxsz; } + + // worst, avg, best case: O(n*m) + void operator=(const DoubleHashSet &temp) { + for (int i = 0; i < mxsz; ++i) + if (state[i] == TAKEN) delete data[i]; + delete[] data; + delete[] state; + + sz = temp.size(); + mxsz = temp.getMaxSize(); + + data = new T *[mxsz](); + state = new State[mxsz](); + + T **tempdata = temp.getData(); + State *tempstate = temp.getState(); + for (int i = 0; i < mxsz; ++i) { + if (tempstate[i] == TAKEN) data[i] = new T(*tempdata[i]); + state[i] = tempstate[i]; + } + } + + private: + int mxsz = 0, sz = 0; + T **data; + State *state; +}; + +void solveBoundedCommandQueue() { + int n, k; + std::cin >> n >> k; + std::cin.ignore(); + std::string s; + ArrayCircularBoundedQueue q(k); + for (int i = 0; i < n; ++i) { + getline(std::cin, s); + if (q.size() == k) q.poll(); + q.offer(s); + } + + q.print(); +} + +void solveCMDWithoutRollbacks() { + std::ios_base::sync_with_stdio(false); + std::cin.tie(0); + std::cout.tie(0); + int n; + std::cin >> n; + std::cin.ignore(); + + DoubleHashSet files; + + for (int i = 0; i < n; ++i) { + std::string cmd, cmdName, fileName; + getline(std::cin, cmd); + + std::stringstream s(cmd); + s >> cmdName; + if (cmdName == "LIST") { + // TODO improve LIST command + files.list(); + std::cout << '\n'; + } else if (cmdName == "NEW") { + s >> fileName; + bool exists = files.contains(fileName); + if (exists) { + std::cout << "ERROR: cannot execute " << cmd << '\n'; + } else { + files.add(fileName); + } + } else { + s >> fileName; + bool exists = files.contains(fileName); + if (exists) { + files.remove(fileName); + } else { + std::cout << "ERROR: cannot execute " << cmd << '\n'; + } + } + } +} + +void solveCMDWithRollbacks() { + std::ios_base::sync_with_stdio(0); + std::cin.tie(0); + std::cout.tie(0); + int n, k; + std::cin >> n >> k; + std::cin.ignore(); + + QueuedBoundedStack> states(k); + DoubleHashSet dummy; + states.push(dummy); + + for (int i = 0; i < n; ++i) { + std::string cmd, cmdName, fileName; + getline(std::cin, cmd); + + std::stringstream s(cmd); + s >> cmdName; + + if (cmdName == "LIST") { + // TODO improve LIST command + states.top().list(); + std::cout << '\n'; + } else if (cmdName == "NEW") { + // auto t1 = high_resolution_clock::now(); + + DoubleHashSet *files = + new DoubleHashSet(states.top()); + s >> fileName; + bool exists = files->contains(fileName); + std::string similar = (fileName.back() == '/' + ? fileName.substr(0, fileName.size() - 1) + : fileName + "/"); + bool existsSimilar = files->contains(similar); + + if (exists || existsSimilar) { + std::cout << "ERROR: cannot execute " << cmd << '\n'; + delete files; + } else { + files->add(fileName); + states.push(files); + // auto t2 = high_resolution_clock::now(); + // auto ms_int = duration_cast(t2 - t1); + // std::cout << ms_int.count() << "ms\n"; + + continue; + } + + } else if (cmdName == "REMOVE") { + DoubleHashSet *files = + new DoubleHashSet(states.top()); + s >> fileName; + bool exists = files->contains(fileName); + + if (exists) { + files->remove(fileName); + states.push(files); + continue; + } else { + std::cout << "ERROR: cannot execute " << cmd << '\n'; + delete files; + } + } else if (cmdName == "UNDO") { + int times = 1; + if (cmd != "UNDO") s >> times; + if (states.size() > times) { + while (times--) { + states.pop(); + } + } else { + std::cout << "ERROR: cannot execute " << cmd << '\n'; + } + + } else { + std::cout << "ERROR: cannot execute " << cmd << '\n'; + } + } +} + +int main() { + // solveBoundedCommandQueue(); + // solveCMDWithoutRollbacks(); + solveCMDWithRollbacks(); +} + diff --git a/assignment1dsa/test.txt b/assignment1dsa/test.txt new file mode 100644 index 0000000..d1361cd --- /dev/null +++ b/assignment1dsa/test.txt @@ -0,0 +1,1001 @@ +1000 36 +NEW 0 +UNDO +NEW 2 +NEW 3 +NEW 4 +NEW 5 +NEW 6 +NEW 7 +NEW 8 +NEW 9 +NEW 10 +NEW 11 +NEW 12 +NEW 13 +NEW 14 +NEW 15 +NEW 16 +NEW 17 +NEW 18 +NEW 19 +NEW 20 +NEW 21 +NEW 22 +NEW 23 +NEW 24 +NEW 25 +NEW 26 +NEW 27 +NEW 28 +NEW 29 +NEW 30 +NEW 31 +NEW 32 +NEW 33 +NEW 34 +NEW 35 +NEW 36 +UNDO +NEW 38 +NEW 39 +NEW 40 +NEW 41 +NEW 42 +NEW 43 +NEW 44 +NEW 45 +NEW 46 +NEW 47 +NEW 48 +NEW 49 +NEW 50 +NEW 51 +NEW 52 +NEW 53 +NEW 54 +NEW 55 +NEW 56 +NEW 57 +NEW 58 +NEW 59 +NEW 60 +NEW 61 +NEW 62 +NEW 63 +NEW 64 +NEW 65 +NEW 66 +NEW 67 +NEW 68 +NEW 69 +NEW 70 +NEW 71 +NEW 72 +UNDO +NEW 74 +NEW 75 +NEW 76 +NEW 77 +NEW 78 +NEW 79 +NEW 80 +NEW 81 +NEW 82 +NEW 83 +NEW 84 +NEW 85 +NEW 86 +NEW 87 +NEW 88 +NEW 89 +NEW 90 +NEW 91 +NEW 92 +NEW 93 +NEW 94 +NEW 95 +NEW 96 +NEW 97 +NEW 98 +NEW 99 +NEW 100 +NEW 101 +NEW 102 +NEW 103 +NEW 104 +NEW 105 +NEW 106 +NEW 107 +NEW 108 +UNDO +NEW 110 +NEW 111 +NEW 112 +NEW 113 +NEW 114 +NEW 115 +NEW 116 +NEW 117 +NEW 118 +NEW 119 +NEW 120 +NEW 121 +NEW 122 +NEW 123 +NEW 124 +NEW 125 +NEW 126 +NEW 127 +NEW 128 +NEW 129 +NEW 130 +NEW 131 +NEW 132 +NEW 133 +NEW 134 +NEW 135 +NEW 136 +NEW 137 +NEW 138 +NEW 139 +NEW 140 +NEW 141 +NEW 142 +NEW 143 +NEW 144 +UNDO +NEW 146 +NEW 147 +NEW 148 +NEW 149 +NEW 150 +NEW 151 +NEW 152 +NEW 153 +NEW 154 +NEW 155 +NEW 156 +NEW 157 +NEW 158 +NEW 159 +NEW 160 +NEW 161 +NEW 162 +NEW 163 +NEW 164 +NEW 165 +NEW 166 +NEW 167 +NEW 168 +NEW 169 +NEW 170 +NEW 171 +NEW 172 +NEW 173 +NEW 174 +NEW 175 +NEW 176 +NEW 177 +NEW 178 +NEW 179 +NEW 180 +UNDO +NEW 182 +NEW 183 +NEW 184 +NEW 185 +NEW 186 +NEW 187 +NEW 188 +NEW 189 +NEW 190 +NEW 191 +NEW 192 +NEW 193 +NEW 194 +NEW 195 +NEW 196 +NEW 197 +NEW 198 +NEW 199 +NEW 200 +NEW 201 +NEW 202 +NEW 203 +NEW 204 +NEW 205 +NEW 206 +NEW 207 +NEW 208 +NEW 209 +NEW 210 +NEW 211 +NEW 212 +NEW 213 +NEW 214 +NEW 215 +NEW 216 +UNDO +NEW 218 +NEW 219 +NEW 220 +NEW 221 +NEW 222 +NEW 223 +NEW 224 +NEW 225 +NEW 226 +NEW 227 +NEW 228 +NEW 229 +NEW 230 +NEW 231 +NEW 232 +NEW 233 +NEW 234 +NEW 235 +NEW 236 +NEW 237 +NEW 238 +NEW 239 +NEW 240 +NEW 241 +NEW 242 +NEW 243 +NEW 244 +NEW 245 +NEW 246 +NEW 247 +NEW 248 +NEW 249 +NEW 250 +NEW 251 +NEW 252 +UNDO +NEW 254 +NEW 255 +NEW 256 +NEW 257 +NEW 258 +NEW 259 +NEW 260 +NEW 261 +NEW 262 +NEW 263 +NEW 264 +NEW 265 +NEW 266 +NEW 267 +NEW 268 +NEW 269 +NEW 270 +NEW 271 +NEW 272 +NEW 273 +NEW 274 +NEW 275 +NEW 276 +NEW 277 +NEW 278 +NEW 279 +NEW 280 +NEW 281 +NEW 282 +NEW 283 +NEW 284 +NEW 285 +NEW 286 +NEW 287 +NEW 288 +UNDO +NEW 290 +NEW 291 +NEW 292 +NEW 293 +NEW 294 +NEW 295 +NEW 296 +NEW 297 +NEW 298 +NEW 299 +NEW 300 +NEW 301 +NEW 302 +NEW 303 +NEW 304 +NEW 305 +NEW 306 +NEW 307 +NEW 308 +NEW 309 +NEW 310 +NEW 311 +NEW 312 +NEW 313 +NEW 314 +NEW 315 +NEW 316 +NEW 317 +NEW 318 +NEW 319 +NEW 320 +NEW 321 +NEW 322 +NEW 323 +NEW 324 +UNDO +NEW 326 +NEW 327 +NEW 328 +NEW 329 +NEW 330 +NEW 331 +NEW 332 +NEW 333 +NEW 334 +NEW 335 +NEW 336 +NEW 337 +NEW 338 +NEW 339 +NEW 340 +NEW 341 +NEW 342 +NEW 343 +NEW 344 +NEW 345 +NEW 346 +NEW 347 +NEW 348 +NEW 349 +NEW 350 +NEW 351 +NEW 352 +NEW 353 +NEW 354 +NEW 355 +NEW 356 +NEW 357 +NEW 358 +NEW 359 +NEW 360 +UNDO +NEW 362 +NEW 363 +NEW 364 +NEW 365 +NEW 366 +NEW 367 +NEW 368 +NEW 369 +NEW 370 +NEW 371 +NEW 372 +NEW 373 +NEW 374 +NEW 375 +NEW 376 +NEW 377 +NEW 378 +NEW 379 +NEW 380 +NEW 381 +NEW 382 +NEW 383 +NEW 384 +NEW 385 +NEW 386 +NEW 387 +NEW 388 +NEW 389 +NEW 390 +NEW 391 +NEW 392 +NEW 393 +NEW 394 +NEW 395 +NEW 396 +UNDO +NEW 398 +NEW 399 +NEW 400 +NEW 401 +NEW 402 +NEW 403 +NEW 404 +NEW 405 +NEW 406 +NEW 407 +NEW 408 +NEW 409 +NEW 410 +NEW 411 +NEW 412 +NEW 413 +NEW 414 +NEW 415 +NEW 416 +NEW 417 +NEW 418 +NEW 419 +NEW 420 +NEW 421 +NEW 422 +NEW 423 +NEW 424 +NEW 425 +NEW 426 +NEW 427 +NEW 428 +NEW 429 +NEW 430 +NEW 431 +NEW 432 +UNDO +NEW 434 +NEW 435 +NEW 436 +NEW 437 +NEW 438 +NEW 439 +NEW 440 +NEW 441 +NEW 442 +NEW 443 +NEW 444 +NEW 445 +NEW 446 +NEW 447 +NEW 448 +NEW 449 +NEW 450 +NEW 451 +NEW 452 +NEW 453 +NEW 454 +NEW 455 +NEW 456 +NEW 457 +NEW 458 +NEW 459 +NEW 460 +NEW 461 +NEW 462 +NEW 463 +NEW 464 +NEW 465 +NEW 466 +NEW 467 +NEW 468 +UNDO +NEW 470 +NEW 471 +NEW 472 +NEW 473 +NEW 474 +NEW 475 +NEW 476 +NEW 477 +NEW 478 +NEW 479 +NEW 480 +NEW 481 +NEW 482 +NEW 483 +NEW 484 +NEW 485 +NEW 486 +NEW 487 +NEW 488 +NEW 489 +NEW 490 +NEW 491 +NEW 492 +NEW 493 +NEW 494 +NEW 495 +NEW 496 +NEW 497 +NEW 498 +NEW 499 +NEW 500 +NEW 501 +NEW 502 +NEW 503 +NEW 504 +UNDO +NEW 506 +NEW 507 +NEW 508 +NEW 509 +NEW 510 +NEW 511 +NEW 512 +NEW 513 +NEW 514 +NEW 515 +NEW 516 +NEW 517 +NEW 518 +NEW 519 +NEW 520 +NEW 521 +NEW 522 +NEW 523 +NEW 524 +NEW 525 +NEW 526 +NEW 527 +NEW 528 +NEW 529 +NEW 530 +NEW 531 +NEW 532 +NEW 533 +NEW 534 +NEW 535 +NEW 536 +NEW 537 +NEW 538 +NEW 539 +NEW 540 +UNDO +NEW 542 +NEW 543 +NEW 544 +NEW 545 +NEW 546 +NEW 547 +NEW 548 +NEW 549 +NEW 550 +NEW 551 +NEW 552 +NEW 553 +NEW 554 +NEW 555 +NEW 556 +NEW 557 +NEW 558 +NEW 559 +NEW 560 +NEW 561 +NEW 562 +NEW 563 +NEW 564 +NEW 565 +NEW 566 +NEW 567 +NEW 568 +NEW 569 +NEW 570 +NEW 571 +NEW 572 +NEW 573 +NEW 574 +NEW 575 +NEW 576 +UNDO +NEW 578 +NEW 579 +NEW 580 +NEW 581 +NEW 582 +NEW 583 +NEW 584 +NEW 585 +NEW 586 +NEW 587 +NEW 588 +NEW 589 +NEW 590 +NEW 591 +NEW 592 +NEW 593 +NEW 594 +NEW 595 +NEW 596 +NEW 597 +NEW 598 +NEW 599 +NEW 600 +NEW 601 +NEW 602 +NEW 603 +NEW 604 +NEW 605 +NEW 606 +NEW 607 +NEW 608 +NEW 609 +NEW 610 +NEW 611 +NEW 612 +UNDO +NEW 614 +NEW 615 +NEW 616 +NEW 617 +NEW 618 +NEW 619 +NEW 620 +NEW 621 +NEW 622 +NEW 623 +NEW 624 +NEW 625 +NEW 626 +NEW 627 +NEW 628 +NEW 629 +NEW 630 +NEW 631 +NEW 632 +NEW 633 +NEW 634 +NEW 635 +NEW 636 +NEW 637 +NEW 638 +NEW 639 +NEW 640 +NEW 641 +NEW 642 +NEW 643 +NEW 644 +NEW 645 +NEW 646 +NEW 647 +NEW 648 +UNDO +NEW 650 +NEW 651 +NEW 652 +NEW 653 +NEW 654 +NEW 655 +NEW 656 +NEW 657 +NEW 658 +NEW 659 +NEW 660 +NEW 661 +NEW 662 +NEW 663 +NEW 664 +NEW 665 +NEW 666 +NEW 667 +NEW 668 +NEW 669 +NEW 670 +NEW 671 +NEW 672 +NEW 673 +NEW 674 +NEW 675 +NEW 676 +NEW 677 +NEW 678 +NEW 679 +NEW 680 +NEW 681 +NEW 682 +NEW 683 +NEW 684 +UNDO +NEW 686 +NEW 687 +NEW 688 +NEW 689 +NEW 690 +NEW 691 +NEW 692 +NEW 693 +NEW 694 +NEW 695 +NEW 696 +NEW 697 +NEW 698 +NEW 699 +NEW 700 +NEW 701 +NEW 702 +NEW 703 +NEW 704 +NEW 705 +NEW 706 +NEW 707 +NEW 708 +NEW 709 +NEW 710 +NEW 711 +NEW 712 +NEW 713 +NEW 714 +NEW 715 +NEW 716 +NEW 717 +NEW 718 +NEW 719 +NEW 720 +UNDO +NEW 722 +NEW 723 +NEW 724 +NEW 725 +NEW 726 +NEW 727 +NEW 728 +NEW 729 +NEW 730 +NEW 731 +NEW 732 +NEW 733 +NEW 734 +NEW 735 +NEW 736 +NEW 737 +NEW 738 +NEW 739 +NEW 740 +NEW 741 +NEW 742 +NEW 743 +NEW 744 +NEW 745 +NEW 746 +NEW 747 +NEW 748 +NEW 749 +NEW 750 +NEW 751 +NEW 752 +NEW 753 +NEW 754 +NEW 755 +NEW 756 +UNDO +NEW 758 +NEW 759 +NEW 760 +NEW 761 +NEW 762 +NEW 763 +NEW 764 +NEW 765 +NEW 766 +NEW 767 +NEW 768 +NEW 769 +NEW 770 +NEW 771 +NEW 772 +NEW 773 +NEW 774 +NEW 775 +NEW 776 +NEW 777 +NEW 778 +NEW 779 +NEW 780 +NEW 781 +NEW 782 +NEW 783 +NEW 784 +NEW 785 +NEW 786 +NEW 787 +NEW 788 +NEW 789 +NEW 790 +NEW 791 +NEW 792 +UNDO +NEW 794 +NEW 795 +NEW 796 +NEW 797 +NEW 798 +NEW 799 +NEW 800 +NEW 801 +NEW 802 +NEW 803 +NEW 804 +NEW 805 +NEW 806 +NEW 807 +NEW 808 +NEW 809 +NEW 810 +NEW 811 +NEW 812 +NEW 813 +NEW 814 +NEW 815 +NEW 816 +NEW 817 +NEW 818 +NEW 819 +NEW 820 +NEW 821 +NEW 822 +NEW 823 +NEW 824 +NEW 825 +NEW 826 +NEW 827 +NEW 828 +UNDO +NEW 830 +NEW 831 +NEW 832 +NEW 833 +NEW 834 +NEW 835 +NEW 836 +NEW 837 +NEW 838 +NEW 839 +NEW 840 +NEW 841 +NEW 842 +NEW 843 +NEW 844 +NEW 845 +NEW 846 +NEW 847 +NEW 848 +NEW 849 +NEW 850 +NEW 851 +NEW 852 +NEW 853 +NEW 854 +NEW 855 +NEW 856 +NEW 857 +NEW 858 +NEW 859 +NEW 860 +NEW 861 +NEW 862 +NEW 863 +NEW 864 +UNDO +NEW 866 +NEW 867 +NEW 868 +NEW 869 +NEW 870 +NEW 871 +NEW 872 +NEW 873 +NEW 874 +NEW 875 +NEW 876 +NEW 877 +NEW 878 +NEW 879 +NEW 880 +NEW 881 +NEW 882 +NEW 883 +NEW 884 +NEW 885 +NEW 886 +NEW 887 +NEW 888 +NEW 889 +NEW 890 +NEW 891 +NEW 892 +NEW 893 +NEW 894 +NEW 895 +NEW 896 +NEW 897 +NEW 898 +NEW 899 +NEW 900 +UNDO +NEW 902 +NEW 903 +NEW 904 +NEW 905 +NEW 906 +NEW 907 +NEW 908 +NEW 909 +NEW 910 +NEW 911 +NEW 912 +NEW 913 +NEW 914 +NEW 915 +NEW 916 +NEW 917 +NEW 918 +NEW 919 +NEW 920 +NEW 921 +NEW 922 +NEW 923 +NEW 924 +NEW 925 +NEW 926 +NEW 927 +NEW 928 +NEW 929 +NEW 930 +NEW 931 +NEW 932 +NEW 933 +NEW 934 +NEW 935 +NEW 936 +UNDO +NEW 938 +NEW 939 +NEW 940 +NEW 941 +NEW 942 +NEW 943 +NEW 944 +NEW 945 +NEW 946 +NEW 947 +NEW 948 +NEW 949 +NEW 950 +NEW 951 +NEW 952 +NEW 953 +NEW 954 +NEW 955 +NEW 956 +NEW 957 +NEW 958 +NEW 959 +NEW 960 +NEW 961 +NEW 962 +NEW 963 +NEW 964 +NEW 965 +NEW 966 +NEW 967 +NEW 968 +NEW 969 +NEW 970 +NEW 971 +NEW 972 +UNDO +NEW 974 +NEW 975 +NEW 976 +NEW 977 +NEW 978 +NEW 979 +NEW 980 +NEW 981 +NEW 982 +NEW 983 +NEW 984 +NEW 985 +NEW 986 +NEW 987 +NEW 988 +NEW 989 +NEW 990 +NEW 991 +NEW 992 +NEW 993 +NEW 994 +NEW 995 +NEW 996 +NEW 997 +NEW 998 +NEW 999 diff --git a/assignment1dsa/tester.cpp b/assignment1dsa/tester.cpp new file mode 100644 index 0000000..5507fb4 --- /dev/null +++ b/assignment1dsa/tester.cpp @@ -0,0 +1,13 @@ +#include +using namespace std ; + +int main() { + cout << "1000 36\n"; + for(int i = 0 ; i < 1000 ; ++i) + { + if(i % 36 == 1) + cout << "UNDO\n"; + else + cout << "NEW " << i << '\n'; + } +} \ No newline at end of file diff --git a/assignment2dsa/CPPLINT.cfg b/assignment2dsa/CPPLINT.cfg new file mode 100644 index 0000000..b61dd2b --- /dev/null +++ b/assignment2dsa/CPPLINT.cfg @@ -0,0 +1,32 @@ +set noparent +root=. +# `build` rules +filter=-build/c++11 +filter=-build/header_guard +filter=-build/include +filter=-build/include_alpha +filter=-build/include_order +filter=-build/include_subdir +filter=-build/include_what_you_use +filter=-build/namespaces +# `legal` rules +filter=-legal/copyright +# `readability` rules +filter=-readability/braces +filter=-readability/casting +filter=-readability/namespace +filter=-readability/todo +# `runtime` rules +filter=-runtime/int +filter=-runtime/references +# `whitespace` rules +filter=-whitespace/blank_line +filter=-whitespace/braces +filter=-whitespace/comments +filter=-whitespace/end_of_line +filter=-whitespace/indent +filter=-whitespace/line_length +filter=-whitespace/newline +filter=-whitespace/operators +filter=-whitespace/parens +filter=-whitespace/tab \ No newline at end of file diff --git a/assignment2dsa/Makefile b/assignment2dsa/Makefile new file mode 100644 index 0000000..be92231 --- /dev/null +++ b/assignment2dsa/Makefile @@ -0,0 +1,22 @@ +CXX = g++ +CXXFLAGS = -O0 -g -Wall -std=c++17 -DDEBUG + +SRC = a.cpp b.cpp c.cpp +OBJ = ${SRC:.cpp=.o} + +all: a b c + +.o: ${OBJ} + ${CXX} -c ${CXXFLAGS} $< + +a: a.o + ${CXX} -o $@ a.o ${LDFLAGS} + +b: b.o + ${CXX} -o $@ b.o ${LDFLAGS} + +c: c.o + ${CXX} -o $@ c.o ${LDFLAGS} + +clean: + rm -f main ${OBJ} \ No newline at end of file diff --git a/assignment2dsa/a.cpp b/assignment2dsa/a.cpp new file mode 100644 index 0000000..76dfb86 --- /dev/null +++ b/assignment2dsa/a.cpp @@ -0,0 +1,273 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAXNUM 4000001 + +class Date { + std::string date; + int year, month, day, total; + void dateToInt() { + year = stoi(date.substr(0, 4)); + month = stoi(date.substr(5, 2)); + day = stoi(date.substr(8, 2)); + total = year * 400 + month * 31 + day; + } + + public: + Date() { + date = "1970-01-01"; + dateToInt(); + } + + explicit Date(const std::string &d) { + date = d; + dateToInt(); + } + + Date(const Date &d) { + date = d.date, year = d.year, month = d.month, day = d.day, + total = d.total; + } + + Date(Date &&d) { + date = std::move(d.date); + year = d.year, month = d.month, day = d.day, total = d.total; + } + + Date &operator=(Date d) { + date = d.date, year = d.year, month = d.month, day = d.day, + total = d.total; + return *this; + } + + bool isLeap(int year) { + if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) return true; + return false; + } + + int maxDay(int month, int year) { + switch (month) { + case 4: + case 6: + case 9: + case 11: + return 30; + break; + case 2: + return (isLeap(year) ? 29 : 28); + break; + default: + return 31; + } + } + + std::string getDate() { return date; } + int getTotal() { return total; } + + void goNextDay() { + day++; + if (day > maxDay(month, year)) day = 1, month++; + if (month > 12) month = 1, year++; + total = year * 400 + month * 31 + day; + + std::stringstream yearss, monthss, dayss; + yearss << std::setfill('0') << std::setw(4) << year; + monthss << std::setfill('0') << std::setw(2) << month; + dayss << std::setfill('0') << std::setw(2) << day; + date = yearss.str() + "-" + monthss.str() + "-" + dayss.str(); + } + + // prefix ++ operator for getting the next day + Date &operator++() { + goNextDay(); + return *this; + } + + Date operator++(int) { + Date res(*this); + goNextDay(); + return res; + } + + operator int() const { return total; } +}; + +class Transaction { + public: + Date date; + double money; + + operator int() { return int(date); } +}; + +// countingsort. Linear complexity. Works only for whole numbers, but can be +// modified to work with negative integers as well. It is perfect for the task, +// since it allows to sort the numbers and to not corrupt the initial order +template +void countingsort(T arr[], size_t n) { + int c[MAXNUM]; + T temp[n + 1]; + std::fill(c, c + MAXNUM, 0); + for (size_t i = 0; i < n; ++i) c[(arr[i])]++; + for (size_t i = 1; i < MAXNUM; ++i) c[i] += c[i - 1]; + for (size_t i = n; i-- > 0;) { + temp[c[int(arr[i])]] = arr[i]; + c[int(arr[i])]--; + } + for (size_t i = 0; i < n; ++i) { + arr[i] = temp[i + 1]; + } +} + +// merge sort. time complexity O(n*logn) in the worst case +template +void mergesortlr(T arr[], size_t l, size_t r) { + if (r - l < 2 || r < l) return; + + size_t m = (l + r) / 2; + mergesortlr(arr, l, m); + mergesortlr(arr, m, r); + + size_t i = 0, j = 0, k = 0; + T temp[r - l]; + while (i < m - l && j < r - m) { + if (arr[l + i] < arr[m + j]) + temp[k++] = arr[l + i++]; + else + temp[k++] = arr[m + j++]; + } + + while (i < m - l) temp[k++] = arr[l + i++]; + + while (j < r - m) temp[k++] = arr[m + j++]; + + for (size_t i = l; i < r; ++i) arr[i] = temp[i - l]; +} + +template +void mergesort(T arr[], size_t sz) { + mergesortlr(arr, 0, sz); +} + +// test a sorting function +template +void testsort(std::function test, size_t sz) { + srand(time(NULL)); + int a[sz], b[sz]; + + for (size_t i = 0; i < sz; ++i) a[i] = b[i] = rand() % 30000; + + using std::chrono::duration; + using std::chrono::duration_cast; + using std::chrono::high_resolution_clock; + using std::chrono::milliseconds; + + // executing test sort + auto t1 = high_resolution_clock::now(); + + test(a, sz); + + auto t2 = high_resolution_clock::now(); + auto ms_int = duration_cast(t2 - t1); + std::cout << "Test sort time: " << ms_int.count() << "ms\n"; + + // executing std::sort + t1 = high_resolution_clock::now(); + + std::sort(b, b + sz); + + t2 = high_resolution_clock::now(); + ms_int = duration_cast(t2 - t1); + std::cout << "std::sort time: " << ms_int.count() << "ms\n"; + + // Checking correctness of the test sort + bool correct = 1; + for (size_t i = 0; i < sz; ++i) { + if (a[i] != b[i]) { + correct = 0; + break; + } + } + + if (correct) + std::cout << "Test sort works properly...\n"; + else + std::cout << "Test sort failed...\n"; +} + +int main() { +#ifdef DEBUG + std::cout << "Testing countingsort:\n"; + testsort(&mergesort, 10000); + std::cout << "\nTesting countingsort:\n"; + testsort(&countingsort, 10000); + + Date feb("2020-02-01"), mar("2020-03-10"); + while (feb != mar) { + std::cout << feb.getDate() << '\n'; + feb++; + } +#endif + + size_t n, d; + std::cin >> n >> d; + Transaction transactions[n]; + for (size_t i = 0; i < n; ++i) { + std::string datestr; + char c; + double money; + std::cin >> datestr >> c >> money; + transactions[i].date = Date(datestr); + transactions[i].money = money; + } + + countingsort(transactions, n); + +#ifdef DEBUG + for (size_t i = 0; i < n; ++i) + std::cout << transactions[i].date.getDate() << ' ' + << transactions[i].money << '\n'; + +#endif + + int ans = 0; + // median + double mid = 0; + // using deque as a queue to iterate through it efficiently + std::deque q; + Date today(transactions[0].date); + + for (size_t i = 0; i < n; ++today) { + double sum = 0; + while (transactions[i].date.getTotal() <= today.getTotal()) { + sum += transactions[i++].money; + if (sum >= mid * 2.0 && q.size() == d) ans++; + if (i >= n) + break; + } + + q.push_back(sum); + if (q.size() > d) q.pop_front(); + + std::vector v; + for (const auto &it : q) v.push_back(it); + + if (v.size() == d) { + mergesort(&v[0], d); + if (d % 2 == 0) + mid = (v[(d - 1) / 2] + v[d / 2]) / 2.0; + else + mid = v[d / 2]; + } + } + + std::cout << ans << '\n'; + + return 0; +} diff --git a/assignment2dsa/b.cpp b/assignment2dsa/b.cpp new file mode 100644 index 0000000..38cd13d --- /dev/null +++ b/assignment2dsa/b.cpp @@ -0,0 +1,379 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Date { + std::string date; + int year, month, day, total; + void dateToInt() { + year = stoi(date.substr(0, 4)); + month = stoi(date.substr(5, 2)); + day = stoi(date.substr(8, 2)); + total = year * 400 + month * 31 + day; + } + + public: + Date() { + date = "1970-01-01"; + dateToInt(); + } + + explicit Date(const std::string& d) { + date = d; + dateToInt(); + } + + Date(const Date& d) { + date = d.date, year = d.year, month = d.month, day = d.day, + total = d.total; + } + + Date(Date&& d) { + date = std::move(d.date); + year = d.year, month = d.month, day = d.day, total = d.total; + } + + Date& operator=(Date d) { + date = d.date, year = d.year, month = d.month, day = d.day, + total = d.total; + return *this; + } + + bool isLeap(int year) { + if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) return true; + return false; + } + + int maxDay(int month, int year) { + switch (month) { + case 4: + case 6: + case 9: + case 11: + return 30; + break; + case 2: + return (isLeap(year) ? 29 : 28); + break; + default: + return 31; + } + } + + std::string getDate() const { return date; } + int getTotal() const { return total; } + + void goNextDay() { + day++; + if (day > maxDay(month, year)) day = 1, month++; + if (month > 12) month = 1, year++; + total = year * 400 + month * 31 + day; + + std::stringstream yearss, monthss, dayss; + yearss << std::setfill('0') << std::setw(4) << year; + monthss << std::setfill('0') << std::setw(2) << month; + dayss << std::setfill('0') << std::setw(2) << day; + date = yearss.str() + "-" + monthss.str() + "-" + dayss.str(); + } + + // prefix ++ operator for getting the next day + Date& operator++() { + goNextDay(); + return *this; + } + + Date operator++(int) { + Date res(*this); + goNextDay(); + return res; + } + + operator int() const { return total; } + + bool operator<(const Date& d) { return (total < d.total); } + bool operator>(const Date& d) { return (total > d.total); } + bool operator<=(const Date& d) { return (total <= d.total); } + bool operator>=(const Date& d) { return (total >= d.total); } + + bool operator==(const Date& d) { return (total == d.total); } + friend std::ostream& operator<<(std::ostream& os, const Date& dt); +}; + +std::ostream& operator<<(std::ostream& os, const Date& dt) { + os << dt.getDate(); + return os; +} + +class Transaction { + public: + Date date; + double money; + + operator int() { return int(date); } +}; + +template +class Btree; + +template +class TreeNode { + std::pair* m_data; + int m_n, m_t; // current number of keys, and the maximum number of keys + TreeNode** m_c; // children + bool m_leaf; // is true if the node is a leaf + + TreeNode(int t, bool leaf) : m_n(0), m_t(t), m_leaf(leaf) { + m_data = new std::pair[2 * t]; + m_c = new TreeNode*[2 * t]; + } + + ~TreeNode() { + delete[] m_data; + if (!m_leaf && m_n > 0) + for (int i = 0; i <= m_n; ++i) delete m_c[i]; + delete[] m_c; + } + + // Insert a new key in the subtree. Assumption: node must be non-full + void insert(K key, V value) { + int i = m_n - 1; // last child + + if (m_leaf) { + // move all greater keys one position right and find the location of + // a new key + while (i >= 0 && m_data[i].first > key) { + m_data[i + 1] = m_data[i]; + i--; + } + + m_data[i + 1] = {key, value}; + m_n++; + } else { + // Find the child which is going to have the new key + while (i >= 0 && m_data[i].first > key) i--; + + // if the child is full + if (m_c[i + 1]->m_n == 2 * m_t - 1) { + splitChild(i + 1, m_c[i + 1]); + + if (m_data[i + 1].first < key) i++; + } + m_c[i + 1]->insert(key, value); + } + } + + // split the child 'child' of this node. Assumption: child must be full + void splitChild(int i, TreeNode* child) { + TreeNode* temp = new TreeNode(child->m_t, child->m_leaf); + temp->m_n = m_t - 1; + + for (int j = 0; j < m_t - 1; j++) + temp->m_data[j] = child->m_data[j + m_t]; + + if (!child->m_leaf) { + for (int j = 0; j < m_t; j++) temp->m_c[j] = child->m_c[j + m_t]; + } + + child->m_n = m_t - 1; + + for (int j = m_n; j >= i + 1; --j) m_c[j + 1] = m_c[j]; + + m_c[i + 1] = temp; + + for (int j = m_n - 1; j >= i; --j) m_data[j + 1] = m_data[j]; + + m_data[i] = child->m_data[m_t - 1]; + + m_n++; + } + + void traverse() { + for (int i = 0; i < m_n; i++) { + if (!m_leaf) m_c[i]->traverse(); + std::cout << m_data[i].first << ' ' << m_data[i].second << ' '; + } + + if (!m_leaf) m_c[m_n]->traverse(); + std::cout << '\n'; + } + + // recursive search O(logn) + const TreeNode* search(K key) const { + int i = 0; + while (i < m_n && m_data[i].first < key) i++; + + if (m_data[i].first == key) return this; + + if (m_leaf == true) return NULL; + + return m_c[i]->search(key); + } + + // range query + std::list search(const K& from, const K& to) const { + std::list res; + if (m_leaf) { + for (int i = 0; i < m_n; ++i) { + if (m_data[i].first >= from && m_data[i].first <= to) + res.push_back(m_data[i].second); + } + } else { + if (m_data[0].first >= from) { + res.splice(res.end(), m_c[0]->search(from, to)); + if (m_data[0].first >= from && m_data[0].first <= to) + res.push_back(m_data[0].second); + } + K prev = m_data[0].first; + for (int i = 1; i < m_n; ++i) { + if (prev > to) break; + if (m_data[i].first >= from) { + res.splice(res.end(), m_c[i]->search(from, to)); + } + if (m_data[i].first >= from && m_data[i].first <= to) + res.push_back(m_data[i].second); + prev = m_data[i].first; + } + if (prev <= to) { + res.splice(res.end(), m_c[m_n]->search(from, to)); + } + } + return res; + } + + friend class Btree; +}; + +template +class IRangeMap { + virtual int size() const = 0; + virtual bool isEmpty() const = 0; + virtual void add(const K& key, const V& value) = 0; + virtual bool contains(const K& key) const = 0; + virtual V& lookup(const K& key) const = 0; + virtual std::list lookupRange(const K& from, const K& to) const = 0; +}; + +template +class Btree : IRangeMap { + TreeNode* m_root; + int m_sz, m_t; + + public: + explicit Btree(int t) : m_root(nullptr), m_sz(0), m_t(t) {} + ~Btree() { delete m_root; } + + // search a key in the tree. Returns a pointer to a TreeNode which has the + // key. + const TreeNode* search(const K& key) const { + return (m_root == NULL) ? NULL : m_root->search(key); + } + + // Return the value of the key. Assumption: key exists in the tree + V& lookup(const K& key) const { + const auto it = search(key); + if (it == NULL) throw "key doesn't exist!"; + for (int i = 0; i < m_t * 2 - 1; ++i) + if (it->m_data[i].first == key) return it->m_data[i].second; + throw "key doesn't exist!"; + } + + bool contains(const K& key) const { return (search(key) != NULL); } + + std::list lookupRange(const K& from, const K& to) const { + if (m_root == NULL) return std::list(); + return m_root->search(from, to); + } + + void traverse() { + if (m_root) m_root->traverse(); + } + + void add(const K& key, const V& value) { + if (key == Date("2021-11-11")) { + Date d = Date("2021-11-11"); + } + if (m_root == NULL) { + m_root = new TreeNode(m_t, true); + m_root->m_data[0] = {key, value}; + m_root->m_n = 1; + } else { + // if root is full + if (m_root->m_n == m_t * 2 - 1) { + TreeNode* temp = new TreeNode(m_t, false); + + // rearrange root and its child + temp->m_c[0] = m_root; + + // split the old root + temp->splitChild(0, m_root); + + int i = 0; + if (temp->m_data[0].first < key) i++; + temp->m_c[i]->insert(key, value); + + m_root = temp; + } else + m_root->insert(key, value); + } + m_sz++; + } + + int size() const { return m_sz; } + + bool isEmpty() const { return (m_sz == 0); } +}; + +int main() { +#ifdef DEBUG + freopen("test", "r", stdin); +#endif + int n; + std::cin >> n; + Btree map(2); + //std::map mp; + for (int i = 0; i < n; ++i) { + std::string datestr, type; + double money; + std::cin >> datestr; + if (datestr == "REPORT") { + std::string from, to; + std::cin >> type >> from >> type >> to; + std::list l = map.lookupRange(Date(from), Date(to)); + double ans = 0, ans2 = 0; + for (const auto& it : l) ans += it; + + /* + auto itfrom = mp.lower_bound(Date(from)), + itto = mp.upper_bound(Date(to)); + for (auto it = itfrom; it != itto; ++it) { + ans2 += it->second; + std::cout << it->first << ' ' << it->second << '\n'; + } + */ + + std::cout << ans << '\n'; + } else { + std::cin >> type >> money; + if (type == "WITHDRAW") money *= -1; + + Date d(datestr); + //mp[d] += money; + if (map.contains(d)) { + map.lookup(d) += money; + } else { + map.add(Date(datestr), money); + } + } + } + +#ifdef DEBUG +#endif +} + diff --git a/assignment2dsa/c.cpp b/assignment2dsa/c.cpp new file mode 100644 index 0000000..b2cf042 --- /dev/null +++ b/assignment2dsa/c.cpp @@ -0,0 +1,163 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MaxN 2147483647 +#define MinN -1 + +template +class Obj { + public: + K k; + V v; + + Obj() {} + Obj(K key, V value) : k(key), v(value) {} + + bool operator<(const Obj &o) const { + if (k == o.k) return (v < o.v); + return (k < o.k); + } + + bool operator>(const Obj &o) const { + if (k == o.k) return (v > o.v); + return (k > o.k); + } + + Obj operator=(const Obj &o) { + k = o.k; + v = o.v; + return *this; + } + + bool operator==(const Obj &o) { + if (k == o.k && v == o.v) + return true; + return false; + } +}; + +template +class IPriorityQueue { + virtual void insert(const Obj &item) = 0; + virtual Obj findMin() = 0; + virtual Obj extractMin() = 0; + virtual void decreaseKey(Obj &item, K newKey) = 0; + virtual void remove(Obj &item) = 0; + virtual void unite(Obj &anotherQueue) = 0; +}; + +template +class PriorityQueue : IPriorityQueue { + Obj *m_data; + int sz, mxsz; + std::unordered_map map; + + public: + PriorityQueue(int capacity) : sz(0), mxsz(capacity) { + m_data = new Obj[capacity](); + } + // get indexes + int parent(int i) { return (i - 1) / 2; } + int left(int i) { return (2 * i + 1); } + int right(int i) { return (2 * i + 2); } + + int findId(const Obj &item) { + // I used unordered_map to find the index of the item by value + return map[item.v]; + } + + Obj findMin() { return m_data[0]; } + + // insert an object. O(logn) + void insert(const Obj &item) { + if (sz == mxsz) { + throw "Couldn't insert!"; + } + + sz++; + int i = sz - 1, j = sz - 1; + m_data[i] = item; + + while (i != 0 && m_data[parent(i)] > m_data[i]) { + swap(m_data[i], m_data[parent(i)]); + j = i; + i = parent(i); + if (i == 0) + break; + } + map[item.v] = j; + } + + // decrease the key of an object. O(logn) + void decreaseKey(Obj &item, K newKey) { + int i = findId(item); + m_data[i].k = newKey; + while (i != 0 && m_data[parent(i)] > m_data[i]) { + swap(m_data[i], m_data[parent(i)]); + i = parent(i); + } + } + + // return minimum and pop it from the queue. O(logn) + Obj extractMin() { + if (sz <= 0) return Obj(MinN, std::string()); + if (sz == 1) { + sz--; + return m_data[0]; + } + + Obj root = m_data[0]; + m_data[0] = m_data[sz - 1]; + sz--; + MinHeapify(0); + + return root; + } + + // delete the object from the queue. O(logn) + void remove(Obj &item) { + decreaseKey(item, K()); + extractMin(); + } + + // stabilize the heap recursively. O(logn) + void MinHeapify(int i) { + int l = left(i); + int r = right(i); + int mn = i; + if (l < sz && m_data[l] < m_data[i]) mn = l; + if (r < sz && m_data[r] < m_data[mn]) mn = r; + if (mn != i) { + swap(m_data[i], m_data[mn]); + MinHeapify(mn); + } + } + + void unite(Obj &anotherQueue) {} +}; + +int main() { + int n; + std::cin >> n; + PriorityQueue q(1000000); + while (n--) { + std::string query, branch; + std::cin >> query; + if (query == "ADD") { + int value; + std::cin >> branch >> value; + q.insert(Obj(value, branch)); + } else { + std::cout << q.extractMin().v << '\n'; + } + } +} diff --git a/assignment2dsa/solutions.pdf b/assignment2dsa/solutions.pdf new file mode 100644 index 0000000..74d8190 Binary files /dev/null and b/assignment2dsa/solutions.pdf differ diff --git a/assignment2dsa/test b/assignment2dsa/test new file mode 100644 index 0000000..315f6ea --- /dev/null +++ b/assignment2dsa/test @@ -0,0 +1,25 @@ +24 +2021-10-18 DEPOSIT 42 +2021-10-09 WITHDRAW 97 +2021-11-01 DEPOSIT 10 +2021-09-07 WITHDRAW 43 +2021-12-09 DEPOSIT 45 +2021-10-08 DEPOSIT 5 +2021-09-22 WITHDRAW 54 +2021-11-25 DEPOSIT 47 +2021-11-02 DEPOSIT 80 +2021-12-05 DEPOSIT 27 +2021-09-22 WITHDRAW 46 +2021-09-21 DEPOSIT 76 +2021-11-15 DEPOSIT 79 +2021-09-12 DEPOSIT 65 +2021-09-12 DEPOSIT 15 +2021-10-16 WITHDRAW 52 +2021-09-10 DEPOSIT 3 +2021-10-12 DEPOSIT 58 +2021-11-01 WITHDRAW 88 +2021-10-02 WITHDRAW 14 +2021-10-03 DEPOSIT 46 +2021-12-08 WITHDRAW 56 +2021-11-11 WITHDRAW 97 +REPORT FROM 2021-09-24 TO 2021-12-12 diff --git a/ski-resort.c b/ski-resort.c new file mode 100644 index 0000000..20a3792 --- /dev/null +++ b/ski-resort.c @@ -0,0 +1,205 @@ +#include +#include +#include +#include + +#ifdef DEBUG +# define D(x) x +#else +# define D(x) +#endif + +struct item { + char name[40] ; + float size ; + int amount; + char mu[10] ; +} ; + +struct rentt { + char name[40] ; + int day, month, year, hours, minutes, seconds ; + struct item items[256] ; +} ; + +int main(int argc, char *argv[]) +{ + FILE * inpf = fopen("input.txt", "r"), + * outf = fopen("output.txt", "w") ; + + // output buffer + char buf[100000] = "\0" ; + + // the actual rent + struct rentt rent[500] ; + + // input + int cur = 0 ; + while(fgets(rent[cur].name, 32, inpf) != NULL) { + + // get rid of \n at the end + int sz = strlen(rent[cur].name) ; + if(rent[cur].name[sz-1] == '\n') + rent[cur].name[--sz] = '\0' ; + + // validate name + if(sz < 2 || sz > 30) + return fprintf(outf, "Invalid input!"), 0 ; + + for(int i = 0 ; i < sz ; ++i) + if(!isalpha(rent[cur].name[i]) && rent[cur].name[i] != ' ') + return fprintf(outf, "Invalid input!"), 0 ; + + // enter date and validate input + char date[100] ; + fgets(date, 100, inpf) ; + if(!(isdigit(date[0]) , isdigit(date[1]) , date[2] == '/' + && isdigit(date[3]) && isdigit(date[4]) && date[5] == '/' + && isdigit(date[6]) && isdigit(date[7]) + && isdigit(date[8]) && isdigit(date[9]) && date[10] == ' ' + && isdigit(date[11]) && isdigit(date[12]) && date[13] == ':' + && isdigit(date[14]) && isdigit(date[15]) && date[16] == ':' + && isdigit(date[17]) && isdigit(date[18]))) + return fprintf(outf, "Invalid input!"), 0 ; + sscanf(date, "%d/%d/%d %d:%d:%d", &rent[cur].day, &rent[cur].month, &rent[cur].year, &rent[cur].hours, &rent[cur].minutes, &rent[cur].seconds) ; + + // validate date + if(rent[cur].month == 1 || rent[cur].month == 3 || rent[cur].month == 5 + || rent[cur].month == 7 || rent[cur].month == 8 + || rent[cur].month == 10 || rent[cur].month == 12) + { + + if(rent[cur].day > 31) + return fprintf(outf, "Invalid input!"), 0 ; + + } else if( rent[cur].month == 2) { + + // leap year case + if(rent[cur].year % 400 == 0) { + if(rent[cur].day > 29) + return fprintf(outf, "Invalid input!"), 0 ; + } else if(rent[cur].year % 4 == 0 && rent[cur].year % 100 != 0) { + if( rent[cur].day > 29) + return fprintf(outf, "Invalid input!"), 0 ; + } else { + if(rent[cur].day > 28) + return fprintf(outf, "Invalid input!"), 0 ; + } + + } else if ( rent[cur].month >= 1 && rent[cur].month <= 12) { + if(rent[cur].day > 30) + return fprintf(outf, "Invalid input!"), 0 ; + } else + return fprintf(outf, "Invalid input!"), 0 ; + + // validate time + + if(!(rent[cur].hours >= 0 && rent[cur].hours <= 23 + && rent[cur].minutes >= 0 && rent[cur].minutes <= 59 + && rent[cur].seconds >= 0 && rent[cur].seconds <= 59)) + return fprintf(outf, "Invalid input!"), 0 ; + + sprintf(buf + strlen(buf), "%s has rented ", rent[cur].name) ; + + int curi = 0 ; + while(1) { + char temp[256] ; + char lol = fgets(temp, 256, inpf) ; + + // check if it is the last line + if(lol == NULL || temp[0] == '\n') break ; + + // get rid of \n at the end + sz = strlen(temp) ; + if(temp[sz-1] == '\n') + temp[--sz] = '\0' ; + if(temp[sz] != '\0') + temp[++sz] = '\0' ; + + + // enter and validate the name of an item + int curp = 0 ; + for(int i = 0 ; i < sz ; ++i) { + if(isalpha(temp[i]) || temp[i] == ' ') { + rent[cur].items[curi].name[curp++] = temp[i] ; + } + else { + if(curp == 0) + return fprintf(outf, "Invalid input!"), 0 ; + + if(rent[cur].items[curi].name[curp-1] == ' ') + rent[cur].items[curi].name[--curp] = '\0' ; + else + return fprintf(outf, "Invalid input!"), 0 ; + break ; + } + } + + // copy only the size, the amount and the measurement unit of an item + char vals[256] ; + memcpy(vals, temp+curp, strlen(temp+curp)+1) ; + // format them + sscanf(vals, "%f%d%s", &rent[cur].items[curi].size, + &rent[cur].items[curi].amount, + rent[cur].items[curi].mu) ; + + D(printf("vals: %s\nsz: %f\nam: %d\nmu: %s\n", + temp, rent[cur].items[curi].size, + rent[cur].items[curi].amount, + rent[cur].items[curi].mu)) ; + // validation + if(!(rent[cur].items[curi].size > 0.0 && rent[cur].items[curi].size <= 200.0 + && rent[cur].items[curi].amount > 0 && rent[cur].items[curi].amount <= 30 + && (strcmp(rent[cur].items[curi].mu, "pair") == 0 + || strcmp(rent[cur].items[curi].mu, "pcs") == 0))) + return fprintf(outf, "Invalid input!"), 0 ; + + // the case when there are several pairs + if(strcmp(rent[cur].items[curi].mu, "pair") == 0 + && rent[cur].items[curi].amount > 1) + sprintf(rent[cur].items[curi].mu, "pairs") ; + + curi ++ ; + } + + // append items to the buffer + if(curi == 1) { + sprintf(buf + strlen(buf), "%d %s of %s of size %g", + rent[cur].items[0].amount, rent[cur].items[0].mu, + rent[cur].items[0].name, rent[cur].items[0].size) ; + } else for(int i = 0 ; i < curi ; ++i) + { + if(i == curi-1) + sprintf(buf + strlen(buf), " and %d %s of %s of size %g", + rent[cur].items[i].amount, rent[cur].items[i].mu, + rent[cur].items[i].name, rent[cur].items[i].size) ; + else if(i == 0) + sprintf(buf + strlen(buf), "%d %s of %s of size %g", + rent[cur].items[i].amount, rent[cur].items[i].mu, + rent[cur].items[i].name, rent[cur].items[i].size) ; + else + sprintf(buf + strlen(buf), ", %d %s of %s of size %g", + rent[cur].items[i].amount, rent[cur].items[i].mu, + rent[cur].items[i].name, rent[cur].items[i].size) ; + } + + // if there is no any item + if(curi <= 0) + return fprintf(outf, "Invalid input!"), 0 ; + + // append the date/time to the buffer + sprintf(buf + strlen(buf), " on %d%d/%d%d/%d%d%d%d at %d%d:%d%d:%d%d.\n", + rent[cur].day/10, rent[cur].day%10, + rent[cur].month/10, rent[cur].month%10, + rent[cur].year/1000, rent[cur].year/100%10, + rent[cur].year/10%10, rent[cur].year%10, + rent[cur].hours/10, rent[cur].hours%10, + rent[cur].minutes/10, rent[cur].minutes%10, + rent[cur].seconds/10, rent[cur].seconds%10) ; + + cur++ ; + } + + // print out the buffer + fprintf(outf, "%s", buf) ; +} \ No newline at end of file diff --git a/ssadass1b.cpp b/ssadass1b.cpp new file mode 100644 index 0000000..f0e6502 --- /dev/null +++ b/ssadass1b.cpp @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include + +bool isConcat(std::string &s, int pos, std::vector &v, + std::unordered_set st) { + if (st.size() == v.size()) return 1; + + for (int i = 0; i < v.size(); ++i) { + bool ok = 1; + if (st.find(i) != st.end()) continue; + + if (v[i].size() > s.size() - pos) continue; + + for (int j = 0; j < v[i].size(); ++j) { + if (s[pos + j] != v[i][j]) { + ok = 0; + break; + } + } + + if (ok) { + st.insert(i); + if (isConcat(s, pos + v[i].size(), v, st)) return 1; + st.erase(i); + } + } + return 0; +} + +int main() { + std::ifstream in; + std::ofstream out; + in.open("input.txt"); + out.open("output.txt"); + + std::string s, temp; + in >> s; + + std::vector v; + while (in >> temp) { + v.push_back(temp); + } + + for (int i = 0; i < s.size(); ++i) { + std::unordered_set st; + if (isConcat(s, i, v, st)) out << i << ' '; + } +} diff --git a/ssadass1c.cpp b/ssadass1c.cpp new file mode 100644 index 0000000..616c341 --- /dev/null +++ b/ssadass1c.cpp @@ -0,0 +1,161 @@ +#include +#include + +template +class Node { + public: + Node(T item) { + value = item; + next = NULL; + } + + T value; + Node* next; +}; + +template +class List { + Node* head; + int sz; + + public: + List() { + head = NULL; + sz = 0; + } + + // Create a list from nodes. O(n) + List(Node* node) { + head = node; + sz = 1; + while (node->next != NULL) sz++; + } + + int size() const { return sz; } + + Node* begin() const { return head; } + + // Return the n'th Node address O(n) + Node* seek(int pos) const { + Node* cur = head; + for (int i = 0; i < pos; ++i) { + cur = cur->next; + } + return cur; + } + + // Remove the next node O(1) + void remove(Node* node) { + Node* nextNode = node->next; + node->next = nextNode->next; + delete nextNode; + sz--; + } + + // remove the n'th node O(n) + void remove(int nodeNumber) { + if (sz == 0) std::abort(); + + Node* cur = head; + + if (nodeNumber == 0) { + head = head->next; + delete cur; + sz--; + return; + } + + for (int i = 0; i < nodeNumber - 1; ++i) { + cur = cur->next; + } + + remove(cur); + } + + // insert a Node. O(n) + void insert(Node* node, int pos) { + Node* cur = head; + + if (pos > sz) std::abort(); + + if (pos == 0) { + node->next = head; + head = node; + sz++; + return; + } + + for (int i = 0; i < pos - 1; ++i) { + cur = cur->next; + } + + node->next = cur->next; + cur->next = node; + sz++; + } + + // insert a Node. O(n) + void insert(T item, int pos) { + Node* node = new Node(item); + insert(node, pos); + } + + // insert a Node. O(n) + void push_back(Node* node) { insert(node, sz); } + + // insert an item. O(n) + void push_back(T item) { insert(item, sz); } + + // Swap every two adjacent Nodes + void swapAdjacent() { + Node*cur = head, *curNext = head->next, *curPrev = NULL; + + for (int i = 0; i < (sz % 2 ? sz - 1 : sz); i += 2) { + if (curPrev == NULL) + head = curNext; + else + curPrev->next = curNext; + + cur->next = curNext->next; + curNext->next = cur; + + curPrev = cur; + if (cur->next) { + cur = cur->next; + curNext = cur->next; + } + } + } + + // convert the list to string. O(n) + std::string toString() { + std::string ans = ""; + Node* cur = head; + + while (cur) { + ans += std::to_string(cur->value) + " "; + cur = cur->next; + } + + return ans; + } +}; + +int main() { + std::ifstream in; + in.open("input.txt"); + + std::ofstream out; + out.open("output.txt"); + + List l; + + int a; + while (in >> a) { + l.push_back(a); + } + + l.swapAdjacent(); + + out << l.toString() << '\n'; +} diff --git a/ssadass2a.cpp b/ssadass2a.cpp new file mode 100644 index 0000000..6b8d7c4 --- /dev/null +++ b/ssadass2a.cpp @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include + +// find determinant of a square matrix starting from the row 'row' +double det(std::list>> &m, int row) { + if (m.size() == 2) { + double a, b, c, d; + auto it = m.begin(); + a = (**it)[row], c = (**it)[row+1]; + it++; + b = (**it)[row], d = (**it)[row+1]; + return (a * d) - (b * c); + } + + double res = 0; + auto it = m.begin(); + for (size_t i = 0; i < m.size(); ++i) { + // the even rows (else) and odd rows (if) + if (i & 1) { + std::shared_ptr> v = *it; + auto temp = it; + temp++; + m.erase(it); + res -= (*v)[row] * det(m, row + 1); + m.insert(temp, v); + } else { + std::shared_ptr> v = *it; + auto temp = it; + temp++; + m.erase(it); + res += (*v)[row] * det(m, row + 1); + m.insert(temp, v); + } + it++; + } + return res; +} + +int main() { + std::ifstream in; + std::ofstream out; + in.open("input.txt"); + out.open("output.txt"); + char c; + std::vector> v; + for (size_t i = 0; in >> c; ++i) { + if (c == '{' || c == ',') { + v.push_back(std::vector()); + for (size_t j = 0; in >> c; ++j) { + if (c == '{' || c == ',') { + int a; + in >> a; + v[i].push_back(a); + } else { + break; + } + } + } else { + break; + } + } + std::list>> m; + for (size_t i = 0; i < v.size(); ++i) { + m.push_back( + std::make_shared>(std::vector())); + auto it = m.end(); + it--; + + for (size_t j = 0; j < v.size(); ++j) { + (*it)->push_back(v[j][i]); + } + } + + out << det(m, 0) << '\n'; +} diff --git a/ssadass2b.cpp b/ssadass2b.cpp new file mode 100644 index 0000000..2d92d36 --- /dev/null +++ b/ssadass2b.cpp @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include + +// find determinant of a square matrix starting from the row 'row' +double det(std::list>> &m, int row) { + if (m.size() == 2) { + double a, b, c, d; + auto it = m.begin(); + a = (**it)[row], c = (**it)[row + 1]; + it++; + b = (**it)[row], d = (**it)[row + 1]; + return (a * d) - (b * c); + } + + double res = 0; + auto it = m.begin(); + for (size_t i = 0; i < m.size(); ++i) { + // the even rows (else) and odd rows (if) + if (i & 1) { + std::shared_ptr> v = *it; + auto temp = it; + temp++; + m.erase(it); + res -= (*v)[row] * det(m, row + 1); + m.insert(temp, v); + } else { + std::shared_ptr> v = *it; + auto temp = it; + temp++; + m.erase(it); + res += (*v)[row] * det(m, row + 1); + m.insert(temp, v); + } + it++; + } + return res; +} + +int main() { + std::ifstream in; + std::ofstream out; + in.open("input.txt"); + out.open("output.txt"); + char c; + std::vector> v; + for (size_t i = 0; in >> c; ++i) { + if (c == '{' || c == ',') { + v.push_back(std::vector()); + for (size_t j = 0; in >> c; ++j) { + if (c == '{' || c == ',') { + int a; + in >> a; + v[i].push_back(a); + } else { + break; + } + } + } else { + break; + } + } + std::list>> m; + for (size_t i = 0; i < v.size(); ++i) { + m.push_back( + std::make_shared>(std::vector())); + auto it = m.end(); + it--; + + for (size_t j = 0; j < v.size(); ++j) { + (*it)->push_back(v[j][i]); + } + } + + double dt = det(m, 0); + + std::vector> a(3); + a[0].push_back(v[1][1] * v[2][2] - v[1][2] * v[2][1]); + a[0].push_back(v[0][1] * v[2][2] - v[2][1] * v[0][2]); + a[0].push_back(v[0][1] * v[1][2] - v[1][1] * v[0][2]); + + a[1].push_back(v[1][0] * v[2][2] - v[2][0] * v[1][2]); + a[1].push_back(v[0][0] * v[2][2] - v[2][0] * v[0][2]); + a[1].push_back(v[0][0] * v[1][2] - v[1][0] * v[0][2]); + + a[2].push_back(v[1][0] * v[2][1] - v[2][0] * v[1][1]); + a[2].push_back(v[0][0] * v[2][1] - v[2][0] * v[0][1]); + a[2].push_back(v[0][0] * v[1][1] - v[1][0] * v[0][1]); + a[0][1] *= -1; + a[1][0] *= -1; + a[1][2] *= -1; + a[2][1] *= -1; + + out.precision(2); + + for (auto i : a) { + for (auto j : i) { + j /= dt; + out << std::fixed << j << ' '; + } + out << '\n'; + } +} diff --git a/ssadass3.cpp b/ssadass3.cpp new file mode 100644 index 0000000..5f83629 --- /dev/null +++ b/ssadass3.cpp @@ -0,0 +1,166 @@ +#include +#include +#include +#include + +class Matrix { + std::vector> m_data; + + public: + Matrix() {} + + // Copy constructor combined with transpose + Matrix(const Matrix& m, bool transpose = 0) { + const std::vector>& data = m.GetData(); + if (transpose) { + if (data.size()) { + int rows = data[0].size(), cols = data.size(); + m_data.resize(rows); + for (auto& i : m_data) i.resize(cols, 0); + + for (int i = 0; i < rows; ++i) + for (int j = 0; j < cols; ++j) m_data[i][j] = data[j][i]; + } + } else { + m_data = data; + } + } + + // Move constructor + Matrix(Matrix&& m) { m_data = std::move(m.GetData()); } + + // Constructor with size + Matrix(size_t rows, size_t cols) { + m_data.resize(rows); + for (auto& i : m_data) i.resize(cols, 0); + } + + // reference-Getter of m_data + std::vector>& GetData() { return m_data; } + + // Getter of m_data + const std::vector>& GetData() const { return m_data; } + + size_t GetRows() const { return m_data.size(); } + + size_t GetCols() const { + if (m_data.size() == 0) return 0; + return m_data[0].size(); + } + + // Matrix multiplication operator + friend Matrix operator*(const Matrix& m1, const Matrix& m2); + + // Inverse matrix using Gaussian elimination + static Matrix Inverse(const Matrix& m) { + int rows = m.GetRows(), cols = m.GetCols(); + if (rows != cols) + throw std::invalid_argument("Inverse is only for square matrices!"); + + Matrix from(m), res(rows, rows); + std::vector>&datares = res.GetData(), + data = from.GetData(); + + for (int i = 0; i < rows; ++i) datares[i][i] = 1; + + for (int i = 0; i < rows; ++i) { + if (data[i][i] == 0.0) + throw std::invalid_argument("No inverse for this matrix!"); + + for (int j = 0; j < rows; ++j) { + if (i != j) { + double ratio = data[j][i] / data[i][i]; + + for (int k = 0; k < rows; ++k) + data[j][k] -= ratio * data[i][k]; + + for (int k = 0; k < rows; ++k) + datares[j][k] -= ratio * datares[i][k]; + } + } + } + + for (int i = 0; i < rows; ++i) + for (int j = 0; j < rows; ++j) datares[i][j] /= data[i][i]; + + return res; + } + + void print(std::ostream& out) const { + for (const auto& i : m_data) { + for (const auto& j : i) out << j << ' '; + out << '\n'; + } + } +}; + +Matrix operator*(const Matrix& m1, const Matrix& m2) { + size_t rows = m1.GetRows(), cols = m2.GetCols(), mid = m1.GetCols(); + if (mid != m2.GetRows()) throw std::invalid_argument("Couldn't multiply!"); + + Matrix res(rows, cols); + const std::vector>&data1 = m1.GetData(), + &data2 = m2.GetData(); + std::vector>& datares = res.GetData(); + + for (size_t i = 0; i < rows; ++i) { + for (size_t j = 0; j < cols; ++j) { + datares[i][j] = 0; + for (size_t k = 0; k < mid; ++k) { + datares[i][j] += data1[i][k] * data2[k][j]; + } + } + } + + return res; +} + +inline std::ostream& operator<<(std::ostream& out, const Matrix& m) { + m.print(out); + return out; +} + +int main() { + std::ifstream inputtxt("input.txt"); + std::ofstream outputtxt("output.txt"); + +#ifdef DEBUG + std::istream& in = inputtxt; + std::ostream& out = std::cout; +#else + std::istream& in = inputtxt; + std::ostream& out = outputtxt; +#endif + out.precision(2); + + int n, m; + in >> n >> m; + Matrix A(m, n + 1), Y(m, 1); + + // input + std::vector>&a = A.GetData(), &y = Y.GetData(); + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n + 1; ++j) { + if (j == 0) a[i][j] = 1; + if (j < n) + in >> a[i][j + 1]; + else + in >> y[i][0]; + } + } + + out << "A:\n" << std::fixed << A << '\n'; + out << "b:\n" << std::fixed << Y << '\n'; + + Matrix A_T(A, true), // A transpose + A_TA(std::move(A_T * A)), // A transpose multiplied by A + A_TA_inv( + std::move(Matrix::Inverse(A_TA))), // inverse of the previous one + A_TA_invA_T(std::move(A_TA_inv * A_T)), // multiplied by A transpose + ans(std::move(A_TA_invA_T * Y)); // answer x + + out << "A_T*A:\n" << std::fixed << A_TA << '\n'; + out << "(A_T*A)_-1:\n" << std::fixed << A_TA_inv << '\n'; + out << "(A_T*A)_-1*A_T:\n" << std::fixed << A_TA_invA_T << '\n'; + out << "x:\n" << std::fixed << ans << '\n'; +}