Browse Source

initial commit

master
RinRi 1 year ago
commit
a2ce29bf44
19 changed files with 3765 additions and 0 deletions
  1. +196
    -0
      FSA.java
  2. +257
    -0
      FSAtoREGEX.java
  3. +6
    -0
      assignment1dsa/Makefile
  4. +632
    -0
      assignment1dsa/main.cpp
  5. +1001
    -0
      assignment1dsa/test.txt
  6. +13
    -0
      assignment1dsa/tester.cpp
  7. +32
    -0
      assignment2dsa/CPPLINT.cfg
  8. +22
    -0
      assignment2dsa/Makefile
  9. +273
    -0
      assignment2dsa/a.cpp
  10. +379
    -0
      assignment2dsa/b.cpp
  11. +163
    -0
      assignment2dsa/c.cpp
  12. BIN
      assignment2dsa/solutions.pdf
  13. +25
    -0
      assignment2dsa/test
  14. +205
    -0
      ski-resort.c
  15. +51
    -0
      ssadass1b.cpp
  16. +161
    -0
      ssadass1c.cpp
  17. +78
    -0
      ssadass2a.cpp
  18. +105
    -0
      ssadass2b.cpp
  19. +166
    -0
      ssadass3.cpp

+ 196
- 0
FSA.java View File

@@ -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<String> states, alpha, finalState, transitions, warnings;
private String initialState;
private Integer initialStateID;
private ArrayList<ArrayList<Edge>> tr;
private ArrayList<ArrayList<Edge>> tr2way;
private HashMap<String, Integer> stateToInt, alphaToInt;
private HashSet<Integer> 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<String>(Arrays.asList(states.split("states=\\[|,|\\]")));
this.alpha = new ArrayList<String>(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<String>(Arrays.asList(finalState.split("fin\\.st=\\[|,|\\]")));
this.transitions =
new ArrayList<String>(Arrays.asList(transitions.split("trans=\\[|,|\\]")));

this.szs = this.states.size();
this.sza = this.alpha.size();

stateToInt = new HashMap<String, Integer>();
alphaToInt = new HashMap<String, Integer>();
isFinal = new HashSet<Integer>();
tr = new ArrayList<ArrayList<Edge>>();
tr2way = new ArrayList<ArrayList<Edge>>();
for (int i = 0; i < this.states.size(); ++i) {
tr.add(new ArrayList<Edge>());
tr2way.add(new ArrayList<Edge>());
}
warnings = new ArrayList<String>();
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<Integer> st = new HashSet<Integer>();
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);
}
}

+ 257
- 0
FSAtoREGEX.java View File

@@ -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<String> states, alpha, finalState, transitions;
private String initialState;
private Integer initialStateID;
private ArrayList<ArrayList<Edge>> tr;
private ArrayList<ArrayList<Edge>> tr2way;
private HashMap<String, Integer> stateToInt, alphaToInt;
private HashSet<Integer> isFinal;
private FileWriter out;
private Integer szs, sza;
private Boolean used[];
private ArrayList<ArrayList<ArrayList<String>>> 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<String>(Arrays.asList(states.split("states=\\[|,|\\]")));
this.alpha = new ArrayList<String>(Arrays.asList(alpha.split("alpha=\\[|,|\\]")));
this.finalState =
new ArrayList<String>(Arrays.asList(finalState.split("accepting=\\[|,|\\]")));
this.transitions =
new ArrayList<String>(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<String, Integer>();
alphaToInt = new HashMap<String, Integer>();
isFinal = new HashSet<Integer>();
tr = new ArrayList<ArrayList<Edge>>();
tr2way = new ArrayList<ArrayList<Edge>>();
for (int i = 0; i < szs; ++i) {
tr.add(new ArrayList<Edge>());
tr2way.add(new ArrayList<Edge>());
}
used = new Boolean[szs];

// initialize R[k][i][j]; 0 <= k <= n; 0 <= i, j < n;
r = new ArrayList<ArrayList<ArrayList<String>>>();
for (int k = 0; k < szs + 1; k++) {
r.add(new ArrayList<ArrayList<String>>());
for (int i = 0; i < szs; ++i) {
r.get(k).add(new ArrayList<String>());
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<Integer> st = new HashSet<Integer>();
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);
}
}

+ 6
- 0
assignment1dsa/Makefile View File

@@ -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

+ 632
- 0
assignment1dsa/main.cpp View File

@@ -0,0 +1,632 @@
#include <chrono>
#include <fstream>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <unordered_map>

/*
* 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 T>
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 T>
class ArrayCircularBoundedQueue : ICircularBoundedQueue<T> {
public:
ArrayCircularBoundedQueue<T>(int maxSize) {
mxsz = maxSize;
data = new T *[mxsz]();
}

~ArrayCircularBoundedQueue<T>() {
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 T>
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 T>
class QueuedBoundedStack : IBoundedStack<T> {
public:
QueuedBoundedStack<T>(int size) {
q1 = new ArrayCircularBoundedQueue<T>(size);
q2 = new ArrayCircularBoundedQueue<T>(size);
mxsz = size;
}

~QueuedBoundedStack<T>() {
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<T> *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<T> *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<T> *q1, *q2;
int sz = 0, mxsz = 0, cur = 0, curPush = 0;
};

template <class T>
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 T>
class DoubleHashSet : ISet<T> {
public:
// TODO: Write comments about every method

enum State : char { EMPTY = 0, DELETED = 1, TAKEN = 2 };

DoubleHashSet<T>() {
sz = 0;
mxsz = 0;
data = 0;
state = 0;
}

DoubleHashSet<T>(int maxSize) {
mxsz = maxSize;
sz = 0;
data = new T *[mxsz]();
state = new State[mxsz]();
}

// O(n) because of copying
DoubleHashSet<T>(const DoubleHashSet<T> &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<T>() {
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<T> &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<std::string> 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<std::string> 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<DoubleHashSet<std::string>> states(k);
DoubleHashSet<std::string> 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<std::string> *files =
new DoubleHashSet<std::string>(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<milliseconds>(t2 - t1);
// std::cout << ms_int.count() << "ms\n";

continue;
}

} else if (cmdName == "REMOVE") {
DoubleHashSet<std::string> *files =
new DoubleHashSet<std::string>(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();
}


+ 1001
- 0
assignment1dsa/test.txt
File diff suppressed because it is too large
View File


+ 13
- 0
assignment1dsa/tester.cpp View File

@@ -0,0 +1,13 @@
#include <iostream>
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';
}
}

+ 32
- 0
assignment2dsa/CPPLINT.cfg View File

@@ -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

+ 22
- 0
assignment2dsa/Makefile View File

@@ -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}

+ 273
- 0
assignment2dsa/a.cpp View File

@@ -0,0 +1,273 @@
#include <algorithm>
#include <chrono>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <vector>

#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 <typename T>
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 <typename T>
void mergesortlr(T arr[], size_t l, size_t r) {
if (r - l < 2 || r < l) return;

size_t m = (l + r) / 2;
mergesortlr<T>(arr, l, m);
mergesortlr<T>(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 <typename T>
void mergesort(T arr[], size_t sz) {
mergesortlr<T>(arr, 0, sz);
}

// test a sorting function
template <typename T>
void testsort(std::function<void(T arr[], size_t sz)> 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<milliseconds>(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<milliseconds>(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<int>(&mergesort<int>, 10000);
std::cout << "\nTesting countingsort:\n";
testsort<int>(&countingsort<int>, 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<double> 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<double> 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;
}

+ 379
- 0
assignment2dsa/b.cpp View File

@@ -0,0 +1,379 @@
#include <algorithm>
#include <chrono>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <sstream>
#include <vector>

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 <typename K, typename V>
class Btree;

template <typename K, typename V>
class TreeNode {
std::pair<K, V>* m_data;
int m_n, m_t; // current number of keys, and the maximum number of keys
TreeNode<K, V>** m_c; // children
bool m_leaf; // is true if the node is a leaf

TreeNode<K, V>(int t, bool leaf) : m_n(0), m_t(t), m_leaf(leaf) {
m_data = new std::pair<K, V>[2 * t];
m_c = new TreeNode<K, V>*[2 * t];
}

~TreeNode<K, V>() {
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<K, V>* child) {
TreeNode<K, V>* temp = new TreeNode<K, V>(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<K, V>* 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<V> search(const K& from, const K& to) const {
std::list<V> 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<K, V>;
};

template <typename K, typename V>
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<V> lookupRange(const K& from, const K& to) const = 0;
};

template <typename K, typename V>
class Btree : IRangeMap<K, V> {
TreeNode<K, V>* m_root;
int m_sz, m_t;

public:
explicit Btree(int t) : m_root(nullptr), m_sz(0), m_t(t) {}
~Btree<K, V>() { delete m_root; }

// search a key in the tree. Returns a pointer to a TreeNode which has the
// key.
const TreeNode<K, V>* 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<V> lookupRange(const K& from, const K& to) const {
if (m_root == NULL) return std::list<V>();
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<K, V>(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<K, V>* temp = new TreeNode<K, V>(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<Date, double> map(2);
//std::map<Date, double> 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<double> 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
}


+ 163
- 0
assignment2dsa/c.cpp View File

@@ -0,0 +1,163 @@
#include <algorithm>
#include <chrono>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <sstream>
#include <unordered_map>
#include <vector>

#define MaxN 2147483647
#define MinN -1

template <typename K, typename V>
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<K, V> operator=(const Obj<K, V> &o) {
k = o.k;
v = o.v;
return *this;
}

bool operator==(const Obj<K, V> &o) {
if (k == o.k && v == o.v)
return true;
return false;
}
};

template <typename K, typename V>
class IPriorityQueue {
virtual void insert(const Obj<K, V> &item) = 0;
virtual Obj<K, V> findMin() = 0;
virtual Obj<K, V> extractMin() = 0;
virtual void decreaseKey(Obj<K, V> &item, K newKey) = 0;
virtual void remove(Obj<K, V> &item) = 0;
virtual void unite(Obj<K, V> &anotherQueue) = 0;
};

template <typename K, typename V>
class PriorityQueue : IPriorityQueue<K, V> {
Obj<K, V> *m_data;
int sz, mxsz;
std::unordered_map<V, int> map;

public:
PriorityQueue<K, V>(int capacity) : sz(0), mxsz(capacity) {
m_data = new Obj<K, V>[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<K, V> &item) {
// I used unordered_map to find the index of the item by value
return map[item.v];
}

Obj<K, V> findMin() { return m_data[0]; }

// insert an object. O(logn)
void insert(const Obj<K, V> &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<K, V> &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<K, V> extractMin() {
if (sz <= 0) return Obj<K, V>(MinN, std::string());
if (sz == 1) {
sz--;
return m_data[0];
}

Obj<K, V> 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<K, V> &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<K, V> &anotherQueue) {}
};

int main() {
int n;
std::cin >> n;
PriorityQueue<int, std::string> q(1000000);
while (n--) {
std::string query, branch;
std::cin >> query;
if (query == "ADD") {
int value;
std::cin >> branch >> value;
q.insert(Obj<int, std::string>(value, branch));
} else {
std::cout << q.extractMin().v << '\n';
}
}
}

BIN
assignment2dsa/solutions.pdf View File


+ 25
- 0
assignment2dsa/test View File

@@ -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

+ 205
- 0
ski-resort.c View File

@@ -0,0 +1,205 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#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) ;
}

+ 51
- 0
ssadass1b.cpp View File

@@ -0,0 +1,51 @@
#include <fstream>
#include <iostream>
#include <string>
#include <unordered_set>
#include <vector>

bool isConcat(std::string &s, int pos, std::vector<std::string> &v,
std::unordered_set<int> 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<std::string> v;
while (in >> temp) {
v.push_back(temp);
}

for (int i = 0; i < s.size(); ++i) {
std::unordered_set<int> st;
if (isConcat(s, i, v, st)) out << i << ' ';
}
}

+ 161
- 0
ssadass1c.cpp View File

@@ -0,0 +1,161 @@
#include <fstream>
#include <iostream>

template <class T>
class Node {
public:
Node<T>(T item) {
value = item;
next = NULL;
}

T value;
Node<T>* next;
};

template <class T>
class List {
Node<T>* head;
int sz;

public:
List<T>() {
head = NULL;
sz = 0;
}

// Create a list from nodes. O(n)
List<T>(Node<T>* node) {
head = node;
sz = 1;
while (node->next != NULL) sz++;
}

int size() const { return sz; }

Node<T>* begin() const { return head; }

// Return the n'th Node address O(n)
Node<T>* seek(int pos) const {
Node<T>* cur = head;
for (int i = 0; i < pos; ++i) {
cur = cur->next;
}
return cur;
}

// Remove the next node O(1)
void remove(Node<T>* node) {
Node<T>* 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<T>* 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<T>* node, int pos) {
Node<T>* 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<T>* node = new Node<T>(item);
insert(node, pos);
}

// insert a Node. O(n)
void push_back(Node<T>* 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<T>*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<T>* 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<int> l;

int a;
while (in >> a) {
l.push_back(a);
}

l.swapAdjacent();

out << l.toString() << '\n';
}

+ 78
- 0
ssadass2a.cpp View File

@@ -0,0 +1,78 @@
#include <fstream>
#include <iostream>
#include <list>
#include <memory>
#include <vector>

// find determinant of a square matrix starting from the row 'row'
double det(std::list<std::shared_ptr<std::vector<double>>> &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<std::vector<double>> v = *it;
auto temp = it;
temp++;
m.erase(it);
res -= (*v)[row] * det(m, row + 1);
m.insert(temp, v);
} else {
std::shared_ptr<std::vector<double>> 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<std::vector<double>> v;
for (size_t i = 0; in >> c; ++i) {
if (c == '{' || c == ',') {
v.push_back(std::vector<double>());
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<std::shared_ptr<std::vector<double>>> m;
for (size_t i = 0; i < v.size(); ++i) {
m.push_back(
std::make_shared<std::vector<double>>(std::vector<double>()));
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';
}

+ 105
- 0
ssadass2b.cpp View File

@@ -0,0 +1,105 @@
#include <fstream>
#include <iostream>
#include <list>
#include <memory>
#include <vector>

// find determinant of a square matrix starting from the row 'row'
double det(std::list<std::shared_ptr<std::vector<double>>> &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<std::vector<double>> v = *it;
auto temp = it;
temp++;
m.erase(it);
res -= (*v)[row] * det(m, row + 1);
m.insert(temp, v);
} else {
std::shared_ptr<std::vector<double>> 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<std::vector<double>> v;
for (size_t i = 0; in >> c; ++i) {
if (c == '{' || c == ',') {
v.push_back(std::vector<double>());
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<std::shared_ptr<std::vector<double>>> m;
for (size_t i = 0; i < v.size(); ++i) {
m.push_back(
std::make_shared<std::vector<double>>(std::vector<double>()));
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<std::vector<double>> 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';
}
}

+ 166
- 0
ssadass3.cpp View File

@@ -0,0 +1,166 @@
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <vector>

class Matrix {
std::vector<std::vector<double>> m_data;

public:
Matrix() {}

// Copy constructor combined with transpose
Matrix(const Matrix& m, bool transpose = 0) {
const std::vector<std::vector<double>>& 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<std::vector<double>>& GetData() { return m_data; }

// Getter of m_data
const std::vector<std::vector<double>>& 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<std::vector<double>>&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<std::vector<double>>&data1 = m1.GetData(),
&data2 = m2.GetData();
std::vector<std::vector<double>>& 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<std::vector<double>>&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';
}

Loading…
Cancel
Save