Skip to content

Commit

Permalink
10K Kattis points!
Browse files Browse the repository at this point in the history
  • Loading branch information
RussellDash332 committed Jul 7, 2024
1 parent 43e46c4 commit 4e0b661
Show file tree
Hide file tree
Showing 12 changed files with 741 additions and 163 deletions.
170 changes: 89 additions & 81 deletions README.md

Large diffs are not rendered by default.

311 changes: 229 additions & 82 deletions docs/index.html

Large diffs are not rendered by default.

105 changes: 105 additions & 0 deletions src/Another Substring Query Problem/anothersubstringqueryproblem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// https://github.com/stevenhalim/cpbook-code/blob/master/ch6/sa_lcp.cpp
#include <bits/stdc++.h>
using namespace std;

typedef pair<int, int> ii;
typedef vector<int> vi;

class SuffixArray {
private:
vi RA;

void countingSort(int k) {
int maxi = max(300, n);
vi c(maxi, 0);
for (int i = 0; i < n; ++i)
++c[i+k < n ? RA[i+k] : 0];
for (int i = 0, ss = 0; i < maxi; ++i) {
int t = c[i]; c[i] = ss; ss += t;
}
vi temp(n);
for (int i = 0; i < n; ++i)
temp[c[SA[i]+k < n ? RA[SA[i]+k] : 0]++] = SA[i];
swap(SA, temp);
}

void constructSA() {
SA.resize(n);
iota(SA.begin(), SA.end(), 0);
RA.resize(n);
for (int i = 0; i < n; ++i) RA[i] = T[i];
for (int k = 1; k < n; k <<= 1) {
countingSort(k);
countingSort(0);
vi temp(n);
int r = 0;
temp[SA[0]] = r;
for (int i = 1; i < n; ++i)
temp[SA[i]] =
((RA[SA[i]] == RA[SA[i-1]]) && (RA[SA[i]+k] == RA[SA[i-1]+k])) ? r : ++r;
swap(RA, temp);
if (RA[SA[n-1]] == n-1) break;
}
}

public:
string T;
const int n;
vi SA;

SuffixArray(string initialT) : T(initialT), n(initialT.size()) {
constructSA();
}

ii stringMatching(string P) {
int m = (int)P.size();
int lo = 0, hi = n-1;
while (lo < hi) {
int mid = (lo+hi) / 2;
int res = T.compare(SA[mid], m, P);
(res >= 0) ? hi = mid : lo = mid+1;
}
if (T.compare(SA[lo], m, P) != 0) return {-1, -1};
ii ans; ans.first = lo;
hi = n-1;
while (lo < hi) {
int mid = (lo+hi) / 2;
int res = T.compare(SA[mid], m, P);
(res > 0) ? hi = mid : lo = mid+1;
}
if (T.compare(SA[hi], m, P) != 0) --hi;
ans.second = hi;
return ans;
}
};

int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);

int n, lo, hi, k;
unordered_map<string, vi> h, q;
string p, s, t;
getline(cin, s);
cin >> n;
int z[n];
ii ans;
for (int i = 0; i < n; i++) {
cin >> t >> k; h[t].push_back(k); q[t].push_back(i);
}
s += char(0);
SuffixArray sa(s);
for (auto& [t, vv] : h) {
ans = sa.stringMatching(t);
lo = ans.first; hi = ans.second;
vi v;
if (lo+1 || hi+1) {
for (int j = lo; j <= hi; j++) v.push_back(sa.SA[j]);
sort(v.begin(), v.end());
}
for (int i = 0; i < h[t].size(); i++) z[q[t][i]] = (v.size() < h[t][i]) ? -1 : v[h[t][i]-1]+1;
}
for (int i : z) cout << i << '\n';
return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
def smm(s, pp):
def suffix_array_construction(s):
n = len(s)
sa = list(range(n))
ra = [ord(s[i]) for i in range(n)]
k, maxi = 1, max(300, n)
while k < n:
for kk in [k, 0]:
c = [0]*maxi
for i in range(n): c[ra[i+kk] if i+kk<n else 0] += 1
ss, temp = 0, [0]*n
for i in range(maxi): t = c[i]; c[i] = ss; ss += t
for i in range(n):
idx = ra[sa[i]+kk] if sa[i]+kk < n else 0
temp[c[idx]] = sa[i]
c[idx] += 1
sa = temp
temp, r = [0]*n, 0
temp[sa[0]] = r
for i in range(1, n):
r += ra[sa[i]] != ra[sa[i-1]] or ra[sa[i]+k] != ra[sa[i-1]+k]
temp[sa[i]] = r
ra = temp
if ra[sa[n-1]] == n-1: break
k *= 2
return sa
s += '\0'
sa = suffix_array_construction(s)
n = len(s)
matches = []
for p in pp:
m, lo, hi = len(p), 0, n-1
while lo < hi:
mid = (lo+hi)//2
if s[sa[mid]:sa[mid]+m] >= p: hi = mid
else: lo = mid+1
if s[sa[lo]:sa[lo]+m] != p: matches.append([]); continue
l, hi = lo, n-1
while lo < hi:
mid = (lo+hi)//2
if s[sa[mid]:sa[mid]+m] > p: hi = mid
else: lo = mid+1
matches.append(sorted(sa[i] for i in range(l, hi - (s[sa[hi]:sa[hi]+m] != p) + 1)))
return matches

import sys; input = sys.stdin.readline; from array import *
s = input().strip(); h = {}; q = {}; n = int(input()); z = array('i', [0]*n)
for i in range(n):
t, k = input().split(); k = int(k)
if t not in h: h[t] = []; q[t] = []
h[t].append(k); q[t].append(i)
a = [*h]; p = smm(s, a)
for i in range(len(a)):
t = a[i]
for j in range(len(h[t])):
if h[t][j] > len(p[i]): z[q[t][j]] = -1
else: z[q[t][j]] = p[i][h[t][j]-1]+1
print(*z)
4 changes: 4 additions & 0 deletions src/Bazaar/bazaar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
N,*A=map(int,open(W:=0).read().split());V=[Z:=0]*N
for i in range(N):t=i<N/2;V[A[i]-1]=1-t;Z+=(2*t-1)*A[i]+i*t
for i in V:Z-=(W:=W+i)*(1-i)
print(Z)
71 changes: 71 additions & 0 deletions src/Orðla/ordla.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
def add(word, verdict):
temp = {}
for idx in range(len(word)):
if verdict[idx] != 'X':
if word[idx] not in temp:
temp[word[idx]] = 0
temp[word[idx]] += 1
for k in temp:
if k not in freq:
freq[k] = set(range(len(word)))
freq[k] -= set(range(temp[k]))
for idx in range(len(word)):
if verdict[idx] == 'X':
if word[idx] in temp:
freq[word[idx]] = {temp[word[idx]]}
else:
freq[word[idx]] = {0}
for idx in range(len(word)):
if verdict[idx] == '/':
if word[idx] not in kb:
kb[word[idx]] = set(range(len(word)))
kb[word[idx]] -= {idx}
for idx in range(len(word)):
if verdict[idx] == 'O':
if word[idx] not in kb2:
kb2[word[idx]] = set()
kb2[word[idx]].add(idx)
for idx in range(len(word)):
if verdict[idx] == 'X' and word[idx] not in kb and word[idx] not in kb2:
illegal.add(word[idx])

def verify(check):
kb2c = {}
for k in kb2:
kb2c[k] = kb2[k].copy()
for idx in range(len(check)):
if check[idx] in illegal:
return
try:
kb2c[check[idx]].remove(idx)
if not kb2c[check[idx]]:
del kb2c[check[idx]]
except:
if check[idx] in kb and idx not in kb[check[idx]]:
return
freq2 = {}
for k in check:
if k not in freq2:
freq2[k] = 0
freq2[k] += 1
for k in freq2:
if k in freq and freq2[k] not in freq[k]:
return
for k in freq:
if k in freq2:
if min(freq[k]) > freq2[k]:
return
elif min(freq[k]) > 0:
return
if not kb2c:
possible.append(check)

from random import *
N = int(input()); W = [input() for _ in range(N)]
kb, kb2, freq = {}, {}, {}; illegal = set()
while W:
print(word:=choice(W)); W.remove(word); verdict = input(); add(word, verdict)
if verdict == 'O'*5: exit(0)
possible = []
for w in W: verify(w)
W = possible
139 changes: 139 additions & 0 deletions src/Orðla/testing_tool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#!/usr/bin/env python3
#
# Testing tool for the Ordla problem
#
# Usage:
#
# python3 testing_tool.py [-f input_file] <program>
#
# If the -f parameter is not specified, sample 1 is used. Otherwise,
# an input file is needed. The file starts with the number of words
# in the dictionary, followed by the words in the dictionary, one per
# line. For example:
#
# 5
# tolva
# ordla
# stoll
# skjar
# skoli

# You can compile and run your solution as follows.
# - You may have to replace 'python3' by just 'python'.
# - On Windows, you may have to to replace '/' by '\'.

# C++:
# g++ solution.cpp
# python3 testing_tool.py ./a.out

# Java
# javac solution.java
# python3 testing_tool.py java solution

# Python3
# python3 testing_tool.py python3 ./solution.py

# The tool is provided as-is, and you should feel free to make
# whatever alterations or augmentations you like to it.
#
# The tool attempts to detect and report common errors, but it
# is not guaranteed that a program that passes the testing tool
# will be accepted.
#

import argparse
import subprocess
import sys
import traceback
import string
import random
from collections import Counter


def write(p, line):
assert p.poll() is None, 'Program terminated early'
print('Write: {}'.format(line), flush=True)
p.stdin.write('{}\n'.format(line))
p.stdin.flush()


def read(p):
assert p.poll() is None, 'Program terminated early'
line = p.stdout.readline().strip()
assert line != '', 'Read empty line or closed output pipe. Make sure that your program started successfully.'
print('Read: %s' % line, flush=True)
return line


parser = argparse.ArgumentParser(description='Testing tool for the Ordla problem')
parser.add_argument('-f', dest='inputfile', metavar='inputfile', default=None, type=argparse.FileType('r'),
help='Custom input file (defaults to sample 1)')
parser.add_argument('program', nargs='+', help='Your solution')

args = parser.parse_args()
guesses = 0

if args.inputfile is not None:
# Read the input file
with args.inputfile as f:
n = int(f.readline().strip())
assert 1 <= n <= 500, 'n must be between 1 and 500'
words = []
for i in range(n):
word = f.readline().strip()
assert len(word) == 5, 'Each word must consist of 5 letters'
assert set(word) <= set(string.ascii_lowercase), 'Each word must consist of lowercase English letters'
words.append(word)
assert f.readline() == '', 'Extra data at end of input file'
else:
words = [
'tolva',
'ordla',
'stoll',
'skjar',
'skoli',
]

correct_word = random.choice(words)
print('Hidden word: {}'.format(correct_word), flush=True)

with subprocess.Popen(" ".join(args.program), shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE,
universal_newlines=True) as p:
try:
write(p, '%d' % len(words))
for word in words:
write(p, word)
while True:
guess = read(p)
assert len(guess) == 5, 'Each guess must consist of 5 letters'
assert set(guess) <= set(string.ascii_lowercase), 'Each guess must consist of lowercase English letters'
assert guess in words, 'Each guess must be from the dictionary'
guesses += 1

rem = Counter(correct_word)
pattern = ['X']*5
for i, c in enumerate(guess):
if correct_word[i] == c:
pattern[i] = 'O'
rem[c] -= 1
elif rem[c] >= 1:
pattern[i] = '/'
rem[c] -= 1

write(p, ''.join(pattern))

if guess == correct_word:
assert p.stdout.readline() == '', 'Printed extra data after finding hidden word'
assert p.wait() == 0, 'Did not exit cleanly after finishing'
break
if guesses == 10000:
sys.stdout.write('Solution has guessed {} times without finding the hidden word. Is it stuck in a loop?\n'.format(guesses))
sys.stdout.flush()

except:
traceback.print_exc()
finally:
sys.stdout.flush()
sys.stderr.flush()
sys.stdout.write('Solution found the word in {} guesses, exit code: {}\n'.format(guesses, p.wait()))
sys.stdout.flush()
Loading

0 comments on commit 4e0b661

Please sign in to comment.