Merge branch 'master' of github.com:vishap/test
This commit is contained in:
71
puzzles/training/2048.cpp
Normal file
71
puzzles/training/2048.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
VIM: let b:cf5build="clang -std=c++20 -O2 -pthread -lstdc++ -I. {SRC} -o {OUT}"
|
||||
VIM: let b:cf5run="{OUT}"
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
|
||||
void print(const std::vector<int>& row)
|
||||
{
|
||||
for (auto i : row){
|
||||
std::cout << i << ',';
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void push(std::vector<int> row)
|
||||
{
|
||||
print(row);
|
||||
auto q = row.begin();
|
||||
auto pe = row.end();
|
||||
for (auto p = row.begin()+1; p != pe; ++p){
|
||||
if (*p==0){
|
||||
continue;
|
||||
}
|
||||
else if (*q == 0){
|
||||
*q+=*p;
|
||||
*p = 0;
|
||||
}
|
||||
else if (*q == *p){
|
||||
*q+=*p;
|
||||
*p = 0;
|
||||
++q;
|
||||
}
|
||||
else {
|
||||
*++q = *p;
|
||||
if (*q != *p){
|
||||
*p = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
print(row);
|
||||
}
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
push({4, 0, 4, 8});
|
||||
|
||||
//......
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
|
||||
121
puzzles/training/a_bit_more_complex_wildcard_match.cpp
Normal file
121
puzzles/training/a_bit_more_complex_wildcard_match.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
VIM: let b:lcppflags="-std=c++14 -O2 -pthread -I."
|
||||
VIM: let b:wcppflags="/O2 /EHsc /DWIN32"
|
||||
VIM-: let b:argv=""
|
||||
*/
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
#include <deque>
|
||||
#include <queue>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <bitset>
|
||||
#include <cstdio>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* Complete the function below.
|
||||
*/
|
||||
bool match(const string& pattern, const string& string) {
|
||||
|
||||
auto s = string.begin();
|
||||
auto p = pattern.begin();
|
||||
|
||||
const std::string::const_iterator empty;
|
||||
auto prev_p = empty;
|
||||
auto prev_s = s;
|
||||
while (s != string.end()) {
|
||||
while ( p != pattern.end() && *p == '*' ) {
|
||||
p++;
|
||||
prev_p = p;
|
||||
prev_s = s;
|
||||
}
|
||||
if ( p == pattern.end() ) {
|
||||
if ( prev_p == p ){
|
||||
return true;
|
||||
} else if ( prev_p != empty ) {
|
||||
p = prev_p;
|
||||
s = ++prev_s;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ( *s == *p ){
|
||||
s++;
|
||||
p++;
|
||||
}
|
||||
else if ( *p == '?' ){
|
||||
s++;
|
||||
p++;
|
||||
}
|
||||
else if ( prev_p != empty ) {
|
||||
p = prev_p;
|
||||
s = ++prev_s;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while ( *p == '*' ) {
|
||||
p++;
|
||||
}
|
||||
return p == pattern.end();
|
||||
}
|
||||
|
||||
|
||||
void test( const std::string& str, const std::string& pattern ){
|
||||
bool res = match(pattern, str);
|
||||
std::cout << str << " - " << pattern << " -> " << res <<std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
#if 1
|
||||
test( "", "" );
|
||||
test( "", "*" );
|
||||
test( "", "?" );
|
||||
test( "a", "?" );
|
||||
test( "abc", "abc" );
|
||||
test( "aaaaabc", "*abc" );
|
||||
test( "aaaaabc", "a*bc" );
|
||||
test( "aaaaabc", "*abc*" );
|
||||
test( "abc", "*abc*" );
|
||||
test( "abc", "****abc*" );
|
||||
test( "abcabaabcabacabc", "a*ba*c" );
|
||||
test( "abcabcabcabccabc", "a*b*cc" );
|
||||
test( "abcabcabcabccabc", "a*b*c?" );
|
||||
test( "abcabcabcabccabc", "a*b*b?*" );
|
||||
test( "abcabcabcabccabc", "*a*?*c*" );
|
||||
test( "abcabcabcabccabc", "****a****??????*c******" );
|
||||
#else
|
||||
ofstream fout(getenv("OUTPUT_PATH"));
|
||||
bool res;
|
||||
string _pattern;
|
||||
getline(cin, _pattern);
|
||||
|
||||
string _string;
|
||||
getline(cin, _string);
|
||||
|
||||
res = match(_pattern, _string);
|
||||
fout << res << endl;
|
||||
|
||||
fout.close();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
136
puzzles/training/add_space_to_make_sentence.cpp
Normal file
136
puzzles/training/add_space_to_make_sentence.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
VIM: let b:cf5build="clang++ -std=c++20 -O2 -pthread -I. {SRC} -o {OUT}"
|
||||
VIM: let b:cf5run="{OUT}"
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
## Problem Description
|
||||
|
||||
Given an input of a dictionary of words and an input string that does not
|
||||
contain spaces, write a method that returns a string with spaces inserted
|
||||
accordingly.
|
||||
|
||||
## Expected Completion Time
|
||||
|
||||
For unoptimized recursive solution: 25 minutes
|
||||
|
||||
## Problem Complexity Level
|
||||
|
||||
Coding Fluency: Medium
|
||||
|
||||
Problem Solving: Medium
|
||||
|
||||
## Questions the candidate might ask
|
||||
|
||||
1) Do you need to find all combinations of sentences? Always return
|
||||
the sentence with the shorter valid matches.
|
||||
2) What if there are spaces already in the string? Assume there aren't
|
||||
already spaces.
|
||||
3) What are the valid set of characters (eg. uppercase, symbols)? Assume
|
||||
dictionary is always all lowercase and are letters.
|
||||
4) What happens if nothing matches in the dictionary? Return null/none.
|
||||
5) What if there are left over characters in the string? Return null/none.
|
||||
|
||||
## Sample inputs - Expected outputs
|
||||
|
||||
Input: "bloombergisfun", ["bloom","bloomberg","is","fun"]
|
||||
Output: "bloomberg is fun"
|
||||
|
||||
## Input corner cases
|
||||
|
||||
Input: "bloombergisfun", ["bloom", "bloomberg","is"]
|
||||
Output: None/Null
|
||||
|
||||
Input: "bloombergisfun", ["bloom", "berg", "bloomberg","is","fun"]
|
||||
Output: "bloom berg is fun"
|
||||
|
||||
## Runtime complexity
|
||||
|
||||
Recursive Solution: O(2^N)
|
||||
This solution O(N*K) where `K` is max length of word in vocab)
|
||||
|
||||
Note:
|
||||
hashing of a string is not an O(1) function, but O(N) therefore complexity
|
||||
is O(N*K^2). But it can be made O(N*K).
|
||||
|
||||
*/
|
||||
|
||||
using dict_t = std::unordered_set<std::string>;
|
||||
|
||||
std::string solution(const std::string& str, const dict_t& dict)
|
||||
{
|
||||
size_t minw = str.size() +1;
|
||||
size_t maxw = 0;
|
||||
for (const auto& w : dict){
|
||||
minw = std::min(minw, w.size());
|
||||
maxw = std::max(maxw, w.size());
|
||||
}
|
||||
|
||||
std::vector<std::string> memo(str.size()+1, std::string());
|
||||
|
||||
for (size_t i = 0; i < str.size(); ++i){
|
||||
if (i != 0 && memo[i].empty()){
|
||||
continue;
|
||||
}
|
||||
for (size_t j = minw; j <= maxw && i+j <= str.size(); ++j){
|
||||
std::string candidate(str.data()+i, j);
|
||||
auto it = dict.find(candidate);
|
||||
if (it != dict.end()){
|
||||
memo[i+j]=memo[i] + " " + *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return memo[str.size()];
|
||||
}
|
||||
|
||||
void test(const std::string& str, const dict_t& dict)
|
||||
{
|
||||
std::cout << "dict=[";
|
||||
bool first = true;
|
||||
for (const auto& word : dict){
|
||||
if (first){
|
||||
first = false;
|
||||
} else {
|
||||
std::cout <<", ";
|
||||
}
|
||||
std::cout << word;
|
||||
}
|
||||
std::cout << "]\n";
|
||||
std::cout << "str='" << str << "' -> ";
|
||||
std::cout.flush();
|
||||
std::cout << "'" << solution(str, dict) << "'\n\n";
|
||||
}
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
test("bloombergisfun", {"bloom","bloomberg","is","fun"});
|
||||
test("bloombergisfun", {"bloom","bloomberg","is"});
|
||||
test("bloombergisfun", {"bloom", "berg", "bloomberg","is","fun"});
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
175
puzzles/training/airport_routes.cpp
Normal file
175
puzzles/training/airport_routes.cpp
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
VIM: let b:cf5build="clang -std=c++20 -O2 -pthread -lstdc++ -I. {SRC} -o {OUT}"
|
||||
VIM: let b:cf5run="{OUT}"
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <functional>
|
||||
|
||||
/*
|
||||
Implement a class called AirMap that has two methods:
|
||||
|
||||
1- add_route(start, destination)
|
||||
- adds a ONE WAY connecting flight from start to destination
|
||||
|
||||
2- print_all_routes(start, destination)
|
||||
- prints all possible routes from start to destination irrespective of hops
|
||||
|
||||
Sample inputs - Expected outputs
|
||||
Given the following flight routes, print all possible routes between the airports C and D
|
||||
|
||||
A ----> B
|
||||
B ----> A
|
||||
A ----> C
|
||||
C ----> A
|
||||
A ----> D
|
||||
D ----> A
|
||||
B ----> C
|
||||
C ----> B
|
||||
B ----> D
|
||||
D ----> B
|
||||
Expected output:
|
||||
|
||||
C,A,B,D,
|
||||
C,A,D,
|
||||
C,B,A,D,
|
||||
C,B,D,
|
||||
|
||||
Input corner cases
|
||||
Find all routes from A to C
|
||||
|
||||
No route example:
|
||||
|
||||
A ----> B
|
||||
C ----> B
|
||||
C ----> A
|
||||
|
||||
Expected output:
|
||||
|
||||
"No route was found" message or an empty output
|
||||
Source equals destination example: Find all routes from A to A
|
||||
|
||||
A ----> B
|
||||
B ----> C
|
||||
C ----> A
|
||||
Expected output:
|
||||
|
||||
A
|
||||
*/
|
||||
|
||||
class AirMap
|
||||
{
|
||||
std::unordered_map<std::string, std::unordered_set<std::string>> graph_;
|
||||
|
||||
public:
|
||||
void add_route(const std::string& start, const std::string& destination)
|
||||
{
|
||||
graph_[start].insert(destination);
|
||||
}
|
||||
|
||||
void print_all_routes(
|
||||
const std::string& start,
|
||||
const std::string& destination) const
|
||||
{
|
||||
std::unordered_set<std::string> visited;
|
||||
std::vector<std::string> path;
|
||||
|
||||
print_all_routes_helper(start, destination, visited, path,
|
||||
[](const std::vector<std::string>& path){
|
||||
for (const auto& node : path){
|
||||
std::cout << node << ',';
|
||||
}
|
||||
std::cout << std::endl;
|
||||
});
|
||||
}
|
||||
|
||||
void print_all_routes_helper(
|
||||
const std::string& start,
|
||||
const std::string& destination,
|
||||
std::unordered_set<std::string>& visited,
|
||||
std::vector<std::string>& path,
|
||||
std::function<void (const std::vector<std::string>& path)> fn) const
|
||||
{
|
||||
visited.insert(start);
|
||||
path.push_back(start);
|
||||
|
||||
if (start == destination){
|
||||
fn(path);
|
||||
} else {
|
||||
const auto it = graph_.find(start);
|
||||
if ( it != graph_.end()){
|
||||
for (const auto& node : it->second){
|
||||
if ( !visited.contains(node) ){
|
||||
print_all_routes_helper(node, destination, visited, path, fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visited.erase(start);
|
||||
path.pop_back();
|
||||
}
|
||||
};
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
|
||||
AirMap map;
|
||||
map.add_route("A","B");
|
||||
map.add_route("B","A");
|
||||
map.add_route("B","D");
|
||||
map.add_route("A","D");
|
||||
map.add_route("A","C");
|
||||
map.add_route("C","A");
|
||||
map.add_route("C","B");
|
||||
map.add_route("B","C");
|
||||
map.add_route("D","A");
|
||||
map.add_route("D","B");
|
||||
|
||||
map.print_all_routes("C", "D");
|
||||
//......
|
||||
|
||||
{
|
||||
std::cout << "---------------------------------------" << std::endl;
|
||||
AirMap map;
|
||||
map.add_route("A","B");
|
||||
map.add_route("C","A");
|
||||
map.add_route("C","B");
|
||||
map.print_all_routes("A", "C");
|
||||
}
|
||||
|
||||
{
|
||||
std::cout << "---------------------------------------" << std::endl;
|
||||
AirMap map;
|
||||
map.add_route("A","B");
|
||||
map.add_route("B","C");
|
||||
map.add_route("C","A");
|
||||
map.print_all_routes("A", "A");
|
||||
}
|
||||
|
||||
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
74
puzzles/training/all_possible_subsets.cpp
Normal file
74
puzzles/training/all_possible_subsets.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
VIM: let b:cf5build="clang -std=c++20 -O2 -pthread -lstdc++ -I. {SRC} -o {OUT}"
|
||||
VIM: let b:cf5run="{OUT}"
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
Problem Description
|
||||
For given set of N elements print all possible subsets.
|
||||
|
||||
Sample inputs - Expected outputs
|
||||
{"a"} ->
|
||||
<- empty set
|
||||
a
|
||||
{"a", "b"} ->
|
||||
<- empty set
|
||||
a
|
||||
b
|
||||
a b
|
||||
Input corner cases
|
||||
Empty input set yields to one empty subset.
|
||||
*/
|
||||
|
||||
void printAllSubsets(const std::vector<std::string> &inputSet, std::ostream &os)
|
||||
{
|
||||
std::vector<bool> subset(inputSet.size(), false);
|
||||
|
||||
while (){
|
||||
|
||||
std::cout << '[';
|
||||
for (size_t i = 0; i < inputSet.size(); ++i){
|
||||
if (subset[i]){
|
||||
std::cout << inputSet[i] << ' ';
|
||||
}
|
||||
}
|
||||
std::cout << ']' << std::endl;
|
||||
|
||||
|
||||
std::
|
||||
|
||||
}
|
||||
std::vector<std::string>
|
||||
|
||||
}
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
|
||||
//......
|
||||
const std::vector<std::string> inputSet = {"a", "b", "c", "d"};
|
||||
printAllSubsets(inputSet, std::cout);
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
89
puzzles/training/array_inversion_count.cpp
Normal file
89
puzzles/training/array_inversion_count.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
VIM: let b:cf5build="clang -std=c++20 -O2 -pthread -lstdc++ -I. {SRC} -o {OUT}"
|
||||
VIM: let b:cf5run="{OUT}"
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <functional>
|
||||
|
||||
/*
|
||||
https://app.codility.com/programmers/lessons/99-future_training/array_inversion_count/
|
||||
|
||||
An array A consisting of N integers is given. An inversion is a pair of indexes (P, Q) such that P < Q and A[Q] < A[P].
|
||||
|
||||
Write a function:
|
||||
|
||||
int solution(vector<int> &A);
|
||||
|
||||
that computes the number of inversions in A, or returns −1 if it exceeds 1,000,000,000.
|
||||
|
||||
For example, in the following array:
|
||||
A[0] = -1 A[1] = 6 A[2] = 3
|
||||
A[3] = 4 A[4] = 7 A[5] = 4
|
||||
|
||||
there are four inversions:
|
||||
(1,2) (1,3) (1,5) (4,5)
|
||||
|
||||
so the function should return 4.
|
||||
|
||||
Write an efficient algorithm for the following assumptions:
|
||||
|
||||
N is an integer within the range [0..100,000];
|
||||
each element of array A is an integer within the range [−2,147,483,648..2,147,483,647].
|
||||
|
||||
*/
|
||||
|
||||
int solution(const std::vector<int>& v)
|
||||
{
|
||||
std::vector<size_t> iv(v.size(),0);
|
||||
for (size_t i=0; i<v.size(); ++i){
|
||||
iv[i] = i;
|
||||
}
|
||||
std::stable_sort(iv.begin(), iv.end(), [&v](size_t op1, size_t op2){
|
||||
return v[op1] < v[op2];
|
||||
});
|
||||
|
||||
size_t count = 0;
|
||||
for (size_t i=0; i < iv.size(); ++i){
|
||||
if ( i < iv[i]){
|
||||
count += iv[i] - i;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::cout << solution({-1, 6, 3, 4, 7, 4}) << std::endl;
|
||||
|
||||
std::cout << solution({0, 0, 0, 1, 1, 1}) << std::endl;
|
||||
std::cout << solution({0, 1, 0, 1, 1, 1}) << std::endl;
|
||||
std::cout << solution({0}) << std::endl;
|
||||
std::cout << solution({}) << std::endl;
|
||||
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
57
puzzles/training/binary_tree_max_path.cpp
Normal file
57
puzzles/training/binary_tree_max_path.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
VIM: let b:lcppflags="-std=c++14 -O2 -pthread -I."
|
||||
VIM: let b:wcppflags="/O2 /EHsc /DWIN32"
|
||||
VIM-: let b:cppflags=g:Iboost.g:Itbb
|
||||
VIM-: let b:ldflags=g:Lboost.g:Ltbb
|
||||
VIM-: let b:ldlibpath=g:Bboost.g:Btbb
|
||||
VIM-: let b:argv=""
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <algorithm>
|
||||
|
||||
struct node
|
||||
{
|
||||
node * left;
|
||||
node * right;
|
||||
int value;
|
||||
};
|
||||
|
||||
long long max_value_of_path_sum( node * root )
|
||||
{
|
||||
if ( !root ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto lm = max_value_of_path_sum( root->left );
|
||||
auto rm = max_value_of_path_sum( root->right );
|
||||
|
||||
return root->value + std::max(lm, rm);
|
||||
}
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
|
||||
//......
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
|
||||
5
puzzles/training/build_and_run_last_changed.sh
Normal file
5
puzzles/training/build_and_run_last_changed.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
SRC=$(ls -t *.cpp | head -1)
|
||||
|
||||
set -x
|
||||
clang -std=c++20 -O2 -pthread -lstdc++ -I. $SRC && ./a.out
|
||||
86
puzzles/training/consolidate_contacts.cpp
Normal file
86
puzzles/training/consolidate_contacts.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
VIM: let b:cf5build="clang -std=c++20 -O2 -pthread -lstdc++ -I. {SRC} -o {OUT}"
|
||||
VIM: let b:cf5run="{OUT}"
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
/*
|
||||
|
||||
std::unordered_map<std::string, std::unordered_set<std::string>>
|
||||
*/
|
||||
|
||||
using contacts_type = std::unordered_map<std::string, std::unordered_set<std::string>>;
|
||||
using emails_type = std::unordered_map<std::string, std::unordered_set<std::string>>;
|
||||
|
||||
|
||||
void
|
||||
all_contacts(
|
||||
const std::string& contact,
|
||||
std::unordered_set<std::string>& visited_contacts,
|
||||
const contacts_type& contacts,
|
||||
const emails_type& emails,
|
||||
std::unordered_set<std::string>& merged_emails)
|
||||
{
|
||||
visited_contacts.insert(contact);
|
||||
for (const auto& email: contacts[contact]){
|
||||
if (merged_emails.count(email)==0){
|
||||
merged_emails.insert(email);
|
||||
for (const auto& merging_contacts : emails[email]){
|
||||
all_contacts(merging_contacts, visited_contacts, contacts, emails, merged_emails );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contacts_type merge( const contacts_type& contacts){
|
||||
|
||||
std::unordered_map<std::string, std::unordered_set<std::string>> emails;
|
||||
|
||||
for (const auto& contact : contacts){
|
||||
for (const auto& email : contact.second){
|
||||
emails[email].insert(contact.first);
|
||||
}
|
||||
}
|
||||
|
||||
contacts_type merged_contacts;
|
||||
std::unordered_set<std::string> visited_contacts;
|
||||
for (const auto& contact : contacts){
|
||||
if (visited_contacts.count(contact.first) == 0){
|
||||
auto& merged_emails = merged_contacts[contact.first];
|
||||
all_contacts(contact.first, visited_contacts, contacts, emails, merged_emails);
|
||||
}
|
||||
}
|
||||
|
||||
return merged_contacts;
|
||||
}
|
||||
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
|
||||
//......
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
61
puzzles/training/constexpr_sqrt.cpp
Normal file
61
puzzles/training/constexpr_sqrt.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
VIM: let b:cf5build="clang -std=c++20 -O2 -pthread -lstdc++ -I. {SRC} -o {OUT}"
|
||||
VIM: let b:cf5run="{OUT}"
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
|
||||
/* This is from "The C++ Programming Language, Fourth Edition
|
||||
* by Bjarne Stroustrup"*/
|
||||
constexpr int sqrt2(int x, int i = 3, int i_sq = 1){
|
||||
return i_sq <= x ? sqrt2(x, i+2, i_sq + i) : i/2-1;
|
||||
}
|
||||
|
||||
/* My simplified version:
|
||||
* Basically sum(1+2*i) where i==0..n-1 == n^2
|
||||
*/
|
||||
constexpr int sqrt(int x, int i = 1, int i_sq = 1){
|
||||
return i_sq <= x ? sqrt(x, i+1, i_sq + (1+2*i)) : i-1;
|
||||
}
|
||||
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::cout << "sqrt(-1)=" << sqrt(-1) << " vs " << sqrt2(-1) << std::endl;
|
||||
std::cout << "sqrt(0)=" << sqrt(0) << " vs " << sqrt2(0) << std::endl;
|
||||
std::cout << "sqrt(1)=" << sqrt(1) << " vs " << sqrt2(1) << std::endl;
|
||||
std::cout << "sqrt(2)=" << sqrt(2) << " vs " << sqrt2(2) << std::endl;
|
||||
std::cout << "sqrt(3)=" << sqrt(3) << " vs " << sqrt2(3) << std::endl;
|
||||
std::cout << "sqrt(4)=" << sqrt(4) << " vs " << sqrt2(4) << std::endl;
|
||||
std::cout << "sqrt(5)=" << sqrt(5) << " vs " << sqrt2(5) << std::endl;
|
||||
std::cout << "sqrt(6)=" << sqrt(6) << " vs " << sqrt2(6) << std::endl;
|
||||
std::cout << "sqrt(9)=" << sqrt(9) << " vs " << sqrt2(9) << std::endl;
|
||||
std::cout << "sqrt(16)=" << sqrt(16) << " vs " << sqrt2(16) << std::endl;
|
||||
std::cout << "sqrt(24)=" << sqrt(24) << " vs " << sqrt2(24) << std::endl;
|
||||
std::cout << "sqrt(25)=" << sqrt(25) << " vs " << sqrt2(25) << std::endl;
|
||||
std::cout << "sqrt(26)=" << sqrt(26) << " vs " << sqrt2(26) << std::endl;
|
||||
std::cout << "sqrt(36)=" << sqrt(36) << " vs " << sqrt2(36) << std::endl;
|
||||
|
||||
//......
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
|
||||
168
puzzles/training/diagonal.cpp
Normal file
168
puzzles/training/diagonal.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
VIM: let b:cf5build="clang -std=c++14 -O2 -pthread -lstdc++ -I. {SRC} -o {OUT}"
|
||||
VIM: let b:cf5run="{OUT}"
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
* Give a N*N square matrix, return an array of its anti-diagonals. Look at the
|
||||
* example for more details.
|
||||
*
|
||||
* Example:
|
||||
* Input:
|
||||
* 1 2 3
|
||||
* 4 5 6
|
||||
* 7 8 9
|
||||
*
|
||||
* Return the following :
|
||||
* [
|
||||
* [1],
|
||||
* [2, 4],
|
||||
* [3, 5, 7],
|
||||
* [6, 8],
|
||||
* [9]
|
||||
* ]
|
||||
*
|
||||
* Input :
|
||||
* 1 2
|
||||
* 3 4
|
||||
*
|
||||
* Return the following :
|
||||
* [
|
||||
* [1],
|
||||
* [2, 3],
|
||||
* [4]
|
||||
* ]
|
||||
*/
|
||||
|
||||
std::vector<std::vector<int> > diagonal(const std::vector<std::vector<int> > &A)
|
||||
{
|
||||
size_t m = A.size();
|
||||
size_t n = A.front().size();
|
||||
|
||||
std::vector<std::vector<int> > v(n+m-1);
|
||||
|
||||
int step = 0;
|
||||
size_t k = 0;
|
||||
for ( size_t i = 0; i < m; ++i, ++k ){
|
||||
size_t c = std::min(i+1, n);
|
||||
v[k].resize(c);
|
||||
for ( size_t j = 0; j < c; ++j){
|
||||
v[k][c-1-j] = A[i-j][j];
|
||||
}
|
||||
}
|
||||
|
||||
for ( size_t i = 1; i < n; ++i, ++k ){
|
||||
size_t c = std::min(n-i, m);
|
||||
v[k].resize(c);
|
||||
for ( size_t j = 0; j < c; ++j){
|
||||
v[k][c-1-j] = A[m-1-j][i+j];
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
std::vector<std::vector<int>> diagonal2(const std::vector<std::vector<int> > &A)
|
||||
{
|
||||
size_t m = A.size();
|
||||
size_t n = A.front().size();
|
||||
size_t mn_min = std::min(n,m);
|
||||
size_t r_count = n+m-1;
|
||||
|
||||
std::vector<std::vector<int>> v(n+m-1);
|
||||
|
||||
for ( int i = 0; i < m; ++i ){
|
||||
for ( int j = 0; j < n; ++j ){
|
||||
size_t r = i+j;
|
||||
|
||||
auto q = i;
|
||||
if ( r >= n ) {
|
||||
q -= r-n+1;
|
||||
}
|
||||
|
||||
if ( !v[r].size() ){
|
||||
auto rr = std::min( r_count-r, r+1);
|
||||
v[r].resize(std::min(rr,mn_min));
|
||||
}
|
||||
|
||||
v[r][q] = A[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
void print( const std::vector<std::vector<int>>& A )
|
||||
{
|
||||
return;
|
||||
for ( const auto& a : A ){
|
||||
for ( auto i : a ){
|
||||
std::cout << i << ' ';
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename SOLUTION>
|
||||
void test( SOLUTION s )
|
||||
{
|
||||
print( s( {
|
||||
{ 1, 2, 3 },
|
||||
{ 4, 5, 6 },
|
||||
{ 7, 8, 9 }
|
||||
} ) );
|
||||
print( s( {
|
||||
{ 1, 2, 3 },
|
||||
{ 4, 5, 6 },
|
||||
{ 7, 8, 9 },
|
||||
{ 10, 11, 12 },
|
||||
{ 13, 14, 15 },
|
||||
{ 16, 17, 18 }
|
||||
} ) );
|
||||
print( s( {
|
||||
{ 1, 2, 3, 4, 5 },
|
||||
{ 6, 7, 8, 9, 10 },
|
||||
{ 11, 12, 13, 14, 15 }
|
||||
} ) );
|
||||
}
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
test(diagonal);
|
||||
test(diagonal2);
|
||||
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
test(diagonal2);
|
||||
|
||||
auto mid = std::chrono::high_resolution_clock::now();
|
||||
|
||||
test(diagonal);
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::chrono::duration<double> seconds1 = mid - begin;
|
||||
std::chrono::duration<double> seconds2 = end - mid;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
std::cout << "Time1: " << seconds1.count() << std::endl;
|
||||
std::cout << "Time2: " << seconds2.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
|
||||
118
puzzles/training/disjoint_intervals.cpp
Normal file
118
puzzles/training/disjoint_intervals.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
[2, 9]
|
||||
[3, 13]
|
||||
[3, 10]
|
||||
[3, 8]
|
||||
[3, 6]
|
||||
[3, 7]
|
||||
[4, 8]
|
||||
[4, 4] *
|
||||
[4, 10]
|
||||
[5, 11]
|
||||
[7, 7] *
|
||||
[7, 8]
|
||||
[7, 12]
|
||||
[7, 15]
|
||||
[9, 12]
|
||||
[9, 10] *
|
||||
|
||||
/*
|
||||
|
||||
Disjoint Intervals (https://www.interviewbit.com/problems/disjoint-intervals/)
|
||||
|
||||
Asked in:
|
||||
Google
|
||||
|
||||
Problem Description
|
||||
|
||||
Given a set of N intervals denoted by 2D array A of size N x 2, the task is to find the length of maximal set of mutually disjoint intervals.
|
||||
|
||||
Two intervals [x, y] & [p, q] are said to be disjoint if they do not have any point in common.
|
||||
|
||||
Return a integer denoting the length of maximal set of mutually disjoint intervals.
|
||||
|
||||
|
||||
|
||||
Problem Constraints
|
||||
|
||||
1 <= N <= 105
|
||||
|
||||
1 <= A[i][0] <= A[i][1] <= 109
|
||||
|
||||
|
||||
|
||||
Input Format
|
||||
|
||||
First and only argument is a 2D array A of size N x 2 denoting the N intervals.
|
||||
|
||||
|
||||
Output Format
|
||||
|
||||
Return a integer denoting the length of maximal set of mutually disjoint intervals.
|
||||
|
||||
|
||||
Example Input
|
||||
|
||||
Input 1:
|
||||
|
||||
A = [
|
||||
[1, 4]
|
||||
[2, 3]
|
||||
[4, 6]
|
||||
[8, 9]
|
||||
]
|
||||
|
||||
Input 2:
|
||||
|
||||
A = [
|
||||
[1, 9]
|
||||
[2, 3]
|
||||
[5, 7]
|
||||
]
|
||||
|
||||
|
||||
|
||||
Example Output
|
||||
|
||||
Output 1:
|
||||
|
||||
3
|
||||
|
||||
Output 2:
|
||||
|
||||
2
|
||||
|
||||
|
||||
|
||||
Example Explanation
|
||||
|
||||
Explanation 1:
|
||||
|
||||
Intervals: [ [1, 4], [2, 3], [4, 6], [8, 9] ]
|
||||
Intervals [2, 3] and [1, 4] overlap.
|
||||
We must include [2, 3] because if [1, 4] is included thenwe cannot include [4, 6].
|
||||
We can include at max three disjoint intervals: [[2, 3], [4, 6], [8, 9]]
|
||||
|
||||
Explanation 2:
|
||||
|
||||
Intervals: [ [1, 9], [2, 3], [5, 7] ]
|
||||
We can include at max two disjoint intervals: [[2, 3], [5, 7]]
|
||||
*/
|
||||
int Solution::solve(vector<vector<int> > &A) {
|
||||
|
||||
std::sort(A.begin(),A.end(),
|
||||
[](const vector<int>& op1, const vector<int>& op2){
|
||||
return (op1[0] < op2[0] );
|
||||
});
|
||||
|
||||
int c = 1;
|
||||
auto it = A.begin();
|
||||
for (auto jt = A.begin()+1; jt != A.end(); ++jt){
|
||||
if (it->at(1) < jt->at(0)){
|
||||
c++;
|
||||
it = jt;
|
||||
} if (jt->at(1) < it->at(1)){
|
||||
it = jt;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
77
puzzles/training/distinct_integer_range.cpp
Normal file
77
puzzles/training/distinct_integer_range.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
VIM: let b:lcppflags="-std=c++14 -O2 -pthread -I."
|
||||
VIM: let b:wcppflags="/O2 /EHsc /DWIN32"
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/*
|
||||
You are given a sorted list of distinct integers from 0 to 99, for
|
||||
instance [0, 1, 2, 50, 52, 75]. Your task is to produce a string
|
||||
that describes numbers missing from the list; in this case
|
||||
"3-49,51,53-74,76-99".
|
||||
|
||||
Examples:
|
||||
|
||||
[] <20>0-99<39>
|
||||
[0] <20>1-99<39>
|
||||
[3, 5] <20>0-2,4,6-99<39>
|
||||
*/
|
||||
|
||||
inline
|
||||
void print_range_if_not_empty(int rb, int re)
|
||||
{
|
||||
if (re - rb > 2) {
|
||||
std::cout << ',' << rb + 1 << '-' << re - 1;
|
||||
}
|
||||
else if (re - rb > 1) {
|
||||
std::cout << ',' << rb + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void print_gaps(std::vector<int> v)
|
||||
{
|
||||
int v_prev = -1;
|
||||
for (int i = 0; i < v.size(); v_prev = v[i++]) {
|
||||
print_range_if_not_empty(v_prev, v[i]);
|
||||
}
|
||||
print_range_if_not_empty(v_prev, 100);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
|
||||
//......
|
||||
print_gaps({ 0, 1, 2, 50, 52, 75 });
|
||||
print_gaps({ 2, 4, 5, 7, 90 });
|
||||
print_gaps({ 0, 4, 5, 7, 99 });
|
||||
|
||||
|
||||
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
79
puzzles/training/find_gaps.cpp
Normal file
79
puzzles/training/find_gaps.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
VIM: let b:lcppflags="-std=c++14 -O2 -pthread -I."
|
||||
VIM: let b:wcppflags="/O2 /EHsc /DWIN32"
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/*
|
||||
google-interview-questions
|
||||
|
||||
You are given a sorted list of distinct integers from 0 to 99, for
|
||||
instance [0, 1, 2, 50, 52, 75]. Your task is to produce a string
|
||||
that describes numbers missing from the list; in this case
|
||||
"3-49,51,53-74,76-99".
|
||||
|
||||
Examples:
|
||||
|
||||
[] <20>0-99<39>
|
||||
[0] <20>1-99<39>
|
||||
[3, 5] <20>0-2,4,6-99<39>
|
||||
*/
|
||||
|
||||
inline
|
||||
void print_range_if_not_empty(int rb, int re)
|
||||
{
|
||||
if (re-rb > 2) {
|
||||
std::cout << ',' << rb + 1 << '-' << re - 1;
|
||||
}
|
||||
else if (re-rb > 1) {
|
||||
std::cout << ',' << rb + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void print_gaps(std::vector<int> v)
|
||||
{
|
||||
int v_prev = -1;
|
||||
for (int i = 0; i < v.size(); v_prev = v[i++]) {
|
||||
print_range_if_not_empty(v_prev, v[i]);
|
||||
}
|
||||
print_range_if_not_empty(v_prev, 100);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
|
||||
//......
|
||||
print_gaps({ 0, 1, 2, 50, 52, 75 });
|
||||
print_gaps({ 2, 4, 5, 7, 90 });
|
||||
print_gaps({ 0, 4, 5, 7, 99 });
|
||||
|
||||
|
||||
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
61
puzzles/training/gas_station.cpp
Normal file
61
puzzles/training/gas_station.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
|
||||
Gas Station
|
||||
|
||||
Asked in:
|
||||
Bloomberg
|
||||
Google
|
||||
DE Shaw
|
||||
Amazon
|
||||
Flipkart
|
||||
|
||||
Given two integer arrays A and B of size N.
|
||||
There are N gas stations along a circular route, where the amount of gas at station i is A[i].
|
||||
|
||||
You have a car with an unlimited gas tank and it costs B[i] of gas to travel from station i
|
||||
to its next station (i+1). You begin the journey with an empty tank at one of the gas stations.
|
||||
|
||||
Return the minimum starting gas station’s index if you can travel around the circuit once, otherwise return -1.
|
||||
|
||||
You can only travel in one direction. i to i+1, i+2, … n-1, 0, 1, 2.. Completing the circuit means starting at i and
|
||||
ending up at i again.
|
||||
|
||||
|
||||
|
||||
Input Format
|
||||
|
||||
The first argument given is the integer array A.
|
||||
The second argument given is the integer array B.
|
||||
|
||||
Output Format
|
||||
|
||||
Return the minimum starting gas station's index if you can travel around the circuit once, otherwise return -1.
|
||||
|
||||
For Example
|
||||
|
||||
Input 1:
|
||||
A = [1, 2]
|
||||
B = [2, 1]
|
||||
Output 1:
|
||||
1
|
||||
Explanation 1:
|
||||
If you start from index 0, you can fill in A[0] = 1 amount of gas. Now your tank has 1 unit of gas. But you need B[0] = 2 gas to travel to station 1.
|
||||
If you start from index 1, you can fill in A[1] = 2 amount of gas. Now your tank has
|
||||
*/
|
||||
int Solution::canCompleteCircuit(const vector<int> &A, const vector<int> &B) {
|
||||
int f = 0;
|
||||
int mf = 0;
|
||||
size_t mi = -1;
|
||||
for (size_t i =0; i < A.size(); ++i){
|
||||
f += A[i]-B[i];
|
||||
if (f < mf){
|
||||
mf = f;
|
||||
mi = i;
|
||||
}
|
||||
if ((i+1) == A.size() && f < 0){
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return (mi+1) % A.size();
|
||||
}
|
||||
120
puzzles/training/goldbachs_conjecture.cpp
Normal file
120
puzzles/training/goldbachs_conjecture.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
|
||||
/*
|
||||
Given an even number ( greater than 2 ), return two prime numbers whose
|
||||
sum will be equal to given number.
|
||||
|
||||
NOTE A solution will always exist. read Goldbach’s conjecture
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
Input : 4
|
||||
Output: 2 + 2 = 4
|
||||
|
||||
If there are more than one solutions possible, return the lexicographically
|
||||
smaller solution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* My understanding is:
|
||||
* The first solution time complexity is O(n^2/log_n) + O(n) memory complexity.
|
||||
* The second solution id O(n^2) complexity + O(0) memory complexity.
|
||||
*/
|
||||
#define SOLUTION 1
|
||||
|
||||
#if SOLUTION == 1
|
||||
|
||||
std::vector<size_t> primes;
|
||||
std::unordered_set<size_t> primes_set;
|
||||
|
||||
void init_primes(const size_t n)
|
||||
{
|
||||
|
||||
std::vector<bool> prime_table(n/2+1, true); // Only odd numbers.
|
||||
primes.push_back(2);
|
||||
|
||||
for (auto p = 3; p <= n; p+=2) {
|
||||
if ( prime_table[p/2] ) {
|
||||
primes.push_back(p);
|
||||
for ( int j = p*3; j <= n; j+=p*2 ) {
|
||||
prime_table[j/2] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
primes_set.insert(primes.begin(), primes.end());
|
||||
}
|
||||
|
||||
std::vector<int> primesum(int A)
|
||||
{
|
||||
for ( int p : primes ){
|
||||
if ( primes_set.find(A-p) != primes_set.end() ) {
|
||||
return {p, A-p};
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
#elif SOLUTION == 2
|
||||
|
||||
bool is_prime(int a)
|
||||
{
|
||||
if ( a <2 )
|
||||
return false;
|
||||
|
||||
int end = std::floor(std::sqrt(a));
|
||||
for ( int i = 2; i <= end; ++i ){
|
||||
if ( a % i == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<int> primesum(int A)
|
||||
{
|
||||
|
||||
for ( int i = 2; i < A; ++i) {
|
||||
if ( is_prime(i) && is_prime(A-i) ){
|
||||
return {i,A-i};
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void solve_and_print(int A){
|
||||
auto r = primesum(A);
|
||||
std::cout << r[0] << ' ' << r[1] << std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
#if SOLUTION == 1
|
||||
init_primes(16777218);
|
||||
#endif
|
||||
|
||||
solve_and_print(4);
|
||||
solve_and_print(10);
|
||||
|
||||
solve_and_print(16777214);
|
||||
solve_and_print(16777218);
|
||||
|
||||
for ( int i = 4; i < 1000000; i+=2 ){
|
||||
primesum(i);
|
||||
}
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
}
|
||||
89
puzzles/training/longest_chain_equal_K.cpp
Normal file
89
puzzles/training/longest_chain_equal_K.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
|
||||
/*
|
||||
VIM: let b:lcppflags="-std=c++14 -O2 -pthread -I."
|
||||
VIM: let b:wcppflags="/O2 /EHsc /DWIN32"
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
/*
|
||||
snap-inc-interview-questions
|
||||
|
||||
You are given an array of integers and a number K. You have to find the any
|
||||
continue sub-array whose elements sum is K. Please note that, the array may
|
||||
have positive, negative, and zeros as its element.
|
||||
|
||||
The desired complexity is O(N).
|
||||
|
||||
Example:
|
||||
Input: [7 0 9 -10 0 789], K = 0
|
||||
Output: Array from index 1 to Index 1.
|
||||
|
||||
Input: [1 2 3 5 -10] K = 0
|
||||
Output: Array from Index 1 to Index 4.
|
||||
|
||||
If K = -2, Output would have been SubArray from Index 2 to Index 4.
|
||||
*/
|
||||
|
||||
void solution( std::vector<int> v, int K )
|
||||
{
|
||||
int f = -1;
|
||||
int l = -2;
|
||||
|
||||
std::unordered_map<int, int> m;
|
||||
int s = 0;
|
||||
for ( int i = 0; i < v.size(); ++i ) {
|
||||
s+= v[i];
|
||||
auto p = m.emplace( s, i);
|
||||
if ( !p.second ){
|
||||
p.first->second = i;
|
||||
}
|
||||
}
|
||||
|
||||
s = 0;
|
||||
for ( int i = 0; i < v.size(); ++i ) {
|
||||
auto r = m.find(s+K);
|
||||
if ( r != m.end() && l-f < r->second - i){
|
||||
l = r->second;
|
||||
f = i;
|
||||
}
|
||||
s+= v[i];
|
||||
}
|
||||
|
||||
std::cout << " {";
|
||||
for ( auto i : v ){
|
||||
std::cout << i << ", ";
|
||||
}
|
||||
std::cout << "}, " << K << " -> (" << f << ", " << l << ")" << std::endl;
|
||||
}
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
|
||||
solution({7, 0, 9, -10, 0, 789}, 0);
|
||||
solution({1, 2, 3, 5, -10}, 0);
|
||||
solution({1, 2, 3, 5, -10}, -2);
|
||||
solution({1, 2, 3, 5, -10}, -10);
|
||||
solution({1, 2, 3, 5, -10}, 1);
|
||||
solution({7, 2, 9, -10, 0, 789}, 7);
|
||||
solution({7, 2, 9, -10, 0, 789}, 10000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
|
||||
34
puzzles/training/majority_element.cpp
Normal file
34
puzzles/training/majority_element.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Majority Element (https://www.interviewbit.com/problems/majority-element/)
|
||||
|
||||
Asked in:
|
||||
Microsoft
|
||||
Yahoo
|
||||
Google
|
||||
Amazon
|
||||
|
||||
Given an array of size n, find the majority element. The majority element is the element that appears more than floor(n/2) times.
|
||||
|
||||
You may assume that the array is non-empty and the majority element always exist in the array.
|
||||
|
||||
Example :
|
||||
|
||||
Input : [2, 1, 2]
|
||||
Return : 2 which occurs 2 times which is greater than 3/2.
|
||||
|
||||
*/
|
||||
int Solution::majorityElement(const vector<int> &A) {
|
||||
int c =0;
|
||||
int e =0;
|
||||
for (int a : A){
|
||||
if (c == 0){
|
||||
e = a;
|
||||
c++;
|
||||
} else if ( e != a ){
|
||||
c--;
|
||||
} else {
|
||||
c++;
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
116
puzzles/training/max_points_on_a_line.cpp
Normal file
116
puzzles/training/max_points_on_a_line.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
VIM: let b:lcppflags="-std=c++14 -O2 -pthread -I."
|
||||
VIM: let b:wcppflags="/O2 /EHsc /DWIN32"
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <atomic>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
/*
|
||||
https://leetcode.com/problems/max-points-on-a-line/
|
||||
|
||||
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
|
||||
*/
|
||||
|
||||
struct Point {
|
||||
int x;
|
||||
int y;
|
||||
Point() : x(0), y(0) {}
|
||||
Point(int a, int b) : x(a), y(b) {}
|
||||
};
|
||||
|
||||
struct pairhash {
|
||||
std::size_t operator() (const Point& p) const {
|
||||
return std::hash<int>()(p.x) ^ std::hash<int>()(p.y);
|
||||
}
|
||||
};
|
||||
|
||||
bool operator == (const Point& p1, const Point& p2) {
|
||||
return p1.x == p2.x && p1.y == p2.y;
|
||||
}
|
||||
|
||||
Point ratio(int x, int y) {
|
||||
if (x == 0) {
|
||||
return Point(0, 1);
|
||||
}
|
||||
else if (y == 0) {
|
||||
return Point(1, 0);
|
||||
}
|
||||
else if ( x < 0 ) {
|
||||
x = -x;
|
||||
y = -y;
|
||||
}
|
||||
|
||||
int a = std::max(abs(x), abs(y));
|
||||
int b = std::min(abs(x), abs(y));
|
||||
for (int c; (c = a % b); a = b, b = c);
|
||||
return Point(x / b, y / b);
|
||||
}
|
||||
|
||||
int solve(const std::vector<Point>& v) {
|
||||
|
||||
std::unordered_map<Point, int, pairhash> vv;
|
||||
for (const auto& p : v) {
|
||||
vv[p]++;
|
||||
}
|
||||
|
||||
if (vv.empty()) {
|
||||
return 0;
|
||||
}
|
||||
else if (vv.size()==1) {
|
||||
return vv.begin()->second;
|
||||
}
|
||||
|
||||
int max_points = 1;
|
||||
for (auto i = vv.begin(); i != vv.end(); i++) {
|
||||
std::unordered_map<Point, int, pairhash> s;
|
||||
for (auto j = std::next(i); j != vv.end(); j++) {
|
||||
const auto line = ratio(i->first.x - j->first.x, i->first.y - j->first.y);
|
||||
s[line] += j->second;
|
||||
max_points = std::max(max_points, s[line] + i->second);
|
||||
}
|
||||
}
|
||||
|
||||
return max_points;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::cout << solve({ { 1,1 },{ 2,2 },{ 3,3 } }) << std::endl;
|
||||
std::cout << solve({ { 1,1 },{ 3,2 },{ 5,3 },{ 4,1 },{ 2,3 },{ 1,4 } }) << std::endl;
|
||||
std::cout << solve({ { 2, 3 },{ 3, 3 },{ -5, 3 } }) << std::endl;
|
||||
std::cout << solve({ { 2, 2 },{ 3, 3 },{ 2, 2 },{ 3, 3 } }) << std::endl;
|
||||
std::cout << solve({ { 2, 2 },{ 2, 3 },{ 3, 2 },{ 3, 3 } }) << std::endl;
|
||||
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
159
puzzles/training/median_stream.cpp
Normal file
159
puzzles/training/median_stream.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
VIM: let b:cf5build="clang -std=c++20 -O2 -pthread -lstdc++ -I. {SRC} -o {OUT}"
|
||||
VIM: let b:cf5run="{OUT}"
|
||||
VIM-: let b:cppflags=g:Iboost.g:Itbb
|
||||
VIM-: let b:ldflags=g:Lboost.g:Ltbb
|
||||
VIM-: let b:ldlibpath=g:Bboost.g:Btbb
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/*
|
||||
Median Stream
|
||||
You're given a list of n integers arr[0..(n-1)]. You must compute a list
|
||||
output[0..(n-1)] such that, for each index i (between 0 and n-1, inclusive),
|
||||
output[i] is equal to the median of the elements arr[0..i] (rounded down to
|
||||
the nearest integer).
|
||||
|
||||
The median of a list of integers is defined as follows. If the integers were
|
||||
to be sorted, then:
|
||||
|
||||
If there are an odd number of integers, then the median is equal to the
|
||||
middle integer in the sorted order.
|
||||
Otherwise, if there are an even number of integers, then the median is equal
|
||||
to the average of the two middle-most integers in the sorted order.
|
||||
|
||||
Input
|
||||
n is in the range [1, 1,000,000].
|
||||
Each value arr[i] is in the range [1, 1,000,000].
|
||||
Output
|
||||
Return a list of n integers output[0..(n-1)], as described above.
|
||||
|
||||
Example 1
|
||||
n = 4
|
||||
arr = [5, 15, 1, 3]
|
||||
output = [5, 10, 5, 4]
|
||||
The median of [5] is 5, the median of [5, 15] is (5 + 15) / 2 = 10,
|
||||
the median of [5, 15, 1] is 5, and the median of [5, 15, 1, 3] is (3 + 5) / 2 = 4.
|
||||
|
||||
Example 2
|
||||
n = 2
|
||||
arr = [1, 2]
|
||||
output = [1, 1]
|
||||
The median of [1] is 1,
|
||||
the median of [1, 2] is (1 + 2) / 2 = 1.5 (which should be rounded down to 1).
|
||||
*/
|
||||
|
||||
std::vector<int> findMedian(std::vector <int> arr) {
|
||||
// Write your code here
|
||||
std::vector<int> r;
|
||||
std::vector<int> l;
|
||||
|
||||
for (size_t i = 0; i < arr.size(); ++i){
|
||||
l.push_back(arr[i]);
|
||||
std::push_heap(l.begin(), l.end());
|
||||
|
||||
if (l.size() > ((i+1)/2+1)){
|
||||
std::pop_heap(l.begin(), l.end());
|
||||
l.resize(l.size()-1);
|
||||
}
|
||||
|
||||
if ((i+1)%2){
|
||||
r.push_back(l[0]);
|
||||
} else if (l.size() == 2){
|
||||
r.push_back( (l[0]+l[1])/2 );
|
||||
} else {
|
||||
r.push_back( (l[0]+std::max(l[1],l[2]))/2 );
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
// These are the tests we use to determine if the solution is correct.
|
||||
// You can add your own at the bottom, but they are otherwise not editable!
|
||||
void printIntegerVector(std::vector <int> array) {
|
||||
int size = array.size();
|
||||
std::cout << "[";
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (i != 0) {
|
||||
std::cout << ", ";
|
||||
}
|
||||
std::cout << array[i];
|
||||
}
|
||||
std::cout << "]";
|
||||
}
|
||||
|
||||
int test_case_number = 1;
|
||||
|
||||
void check(std::vector <int>& expected, std::vector <int>& output) {
|
||||
int expected_size = expected.size();
|
||||
int output_size = output.size();
|
||||
bool result = true;
|
||||
if (expected_size != output_size) {
|
||||
result = false;
|
||||
}
|
||||
for (int i = 0; i < std::min(expected_size, output_size); i++) {
|
||||
result &= (output[i] == expected[i]);
|
||||
}
|
||||
const char* rightTick = "PASS - ";
|
||||
const char* wrongTick = "FAIL - ";
|
||||
if (result) {
|
||||
std::cout << rightTick << "Test #" << test_case_number << "\n";
|
||||
}
|
||||
else {
|
||||
std::cout << wrongTick << "Test #" << test_case_number << ": Expected ";
|
||||
printIntegerVector(expected);
|
||||
std::cout << " Your output: ";
|
||||
printIntegerVector(output);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
test_case_number++;
|
||||
}
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
{
|
||||
std::vector <int> arr_1{5, 15, 1, 3};
|
||||
std::vector <int> expected_1{5, 10, 5, 4};
|
||||
std::vector <int> output_1 = findMedian(arr_1);
|
||||
check(expected_1, output_1);
|
||||
}{
|
||||
std::vector <int> arr_2{2, 4, 7, 1, 5, 3};
|
||||
std::vector <int> expected_2{2, 3, 4, 3, 4, 3};
|
||||
std::vector <int> output_2 = findMedian(arr_2);
|
||||
check(expected_2, output_2);
|
||||
}{
|
||||
std::vector <int> arr_2{2, 4, 7, 1, 5};
|
||||
std::vector <int> expected_2{2, 3, 4, 3, 4};
|
||||
std::vector <int> output_2 = findMedian(arr_2);
|
||||
check(expected_2, output_2);
|
||||
}{
|
||||
std::vector <int> arr_2{2, 4, 7, 1, 5, 3, 4};
|
||||
std::vector <int> expected_2{2, 3, 4, 3, 4, 3, 4 };
|
||||
std::vector <int> output_2 = findMedian(arr_2);
|
||||
check(expected_2, output_2);
|
||||
}
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
148
puzzles/training/multithreaded_queue.cpp
Normal file
148
puzzles/training/multithreaded_queue.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
VIM: let b:lcppflags="-std=c++14 -O2 -pthread -I."
|
||||
VIM: let b:wcppflags="/O2 /EHsc /DWIN32"
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <atomic>
|
||||
|
||||
/*
|
||||
Queue.
|
||||
*/
|
||||
|
||||
thread_local size_t this_tid;
|
||||
|
||||
template <typename M>
|
||||
class MtQueue {
|
||||
|
||||
std::queue<M> m_queue;
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_push_cond;
|
||||
std::condition_variable m_pop_cond;
|
||||
std::atomic<bool> m_stopped;
|
||||
|
||||
static const size_t max_queue = 100;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/* Stop Queue */
|
||||
void stop() {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
m_stopped.store(true);
|
||||
m_pop_cond.notify_all();
|
||||
m_push_cond.notify_all();
|
||||
}
|
||||
|
||||
/* Blocks when */
|
||||
bool push(M m) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
while (m_queue.size() >= max_queue && !m_stopped.load()) {
|
||||
printf(" %lld: is full.\n", this_tid);
|
||||
m_push_cond.wait(lock);
|
||||
}
|
||||
if (m_stopped.load()) {
|
||||
return false;
|
||||
}
|
||||
m_queue.push(m);
|
||||
printf("%lld: size %lld.\n", this_tid, m_queue.size());
|
||||
m_pop_cond.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Blocks when empty.*/
|
||||
bool pop(M& m) {
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
while (m_queue.empty() && !m_stopped.load()) {
|
||||
printf(" %lld: is empty.\n", this_tid);
|
||||
m_pop_cond.wait(lock);
|
||||
}
|
||||
if (m_stopped.load()) {
|
||||
return false;
|
||||
}
|
||||
m = m_queue.front();
|
||||
m_queue.pop();
|
||||
printf("%lld: size %lld.\n", this_tid, m_queue.size());
|
||||
m_push_cond.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void test() {
|
||||
MtQueue<int> q;
|
||||
|
||||
auto push_proc = [&q](size_t tid) {
|
||||
this_tid = tid;
|
||||
int i = 0;
|
||||
while (q.push(2)) {
|
||||
if (++i % 101 == 0) {
|
||||
auto m = std::chrono::milliseconds(100);
|
||||
//printf("%lld: pusher waiting for %lldms.\n", this_tid, m.count());
|
||||
//std::this_thread::sleep_for(m);
|
||||
}
|
||||
}
|
||||
};
|
||||
auto pop_proc = [&q](size_t tid) {
|
||||
this_tid = tid;
|
||||
int m;
|
||||
while (q.pop(m)) {
|
||||
|
||||
//printf("%lld: popper waiting for %dms.\n", this_tid, m);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(m));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
std::vector<std::thread> v;
|
||||
v.reserve(16);
|
||||
v.emplace_back(push_proc, v.size());
|
||||
v.emplace_back(pop_proc, v.size());
|
||||
v.emplace_back(pop_proc, v.size());
|
||||
v.emplace_back(pop_proc, v.size());
|
||||
v.emplace_back(pop_proc, v.size());
|
||||
v.emplace_back(pop_proc, v.size());
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
q.stop();
|
||||
printf(" STOPPING.\n");
|
||||
for (auto& t : v) {
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
while (true) {
|
||||
test();
|
||||
}
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
35
puzzles/training/num_valid_comb.py
Normal file
35
puzzles/training/num_valid_comb.py
Normal file
@@ -0,0 +1,35 @@
|
||||
#
|
||||
# The number of valid combinations of a strings for given input array a[],
|
||||
# where a=>1, z => 26, and 0 <= a[i] <= 9
|
||||
# {1,1,1} => {aaa, ak, ka} => 3
|
||||
# {1,1,0} => {aj} => 1 "/>
|
||||
#
|
||||
|
||||
|
||||
def valid_comb_aux(s, p, b, e, dyn):
|
||||
if b in dyn:
|
||||
print("dyn", p)
|
||||
return dyn[b]
|
||||
if b == e:
|
||||
print("fin", p)
|
||||
return 1
|
||||
count = 0
|
||||
for i in range(b+1, e+1):
|
||||
if 0 < int(s[b:i]) and int(s[b:i]) <= (ord('z')-ord('a')+1):
|
||||
p.extend(chr(ord('a')+int(s[b:i])-1))
|
||||
count = count + valid_comb_aux(s, p, i, e, dyn)
|
||||
p.pop()
|
||||
dyn[b] = count
|
||||
return count
|
||||
|
||||
|
||||
def valid_comb(s):
|
||||
dyn = {}
|
||||
return valid_comb_aux(s, [], 0, len(s), dyn)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(valid_comb("111"))
|
||||
print(valid_comb("110"))
|
||||
print(valid_comb("22222"))
|
||||
# valid_comb("12131456879234522222")
|
||||
115
puzzles/training/number_of_islands.cpp
Normal file
115
puzzles/training/number_of_islands.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
VIM: let b:lcppflags="-std=c++14 -O2 -pthread"
|
||||
VIM: let b:wcppflags="/O2 /EHsc /DWIN32"
|
||||
VIM-: let b:argv=""
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
/*
|
||||
FB On-site March
|
||||
|
||||
Q: Find number of Islands.
|
||||
XXXOO
|
||||
OOOXX
|
||||
XXOOX
|
||||
Return 3 islands.
|
||||
1 1 1 O O
|
||||
O O O 2 2
|
||||
3 3 O O 2
|
||||
*/
|
||||
int number_of_islands( const std::vector<std::string>& board )
|
||||
{
|
||||
auto n = board.size();
|
||||
auto m = board.front().size();
|
||||
std::unordered_map<int,int> g;
|
||||
|
||||
auto idx = [m](size_t i, size_t j){
|
||||
return i*m+j;
|
||||
};
|
||||
|
||||
auto root = [&g](size_t idx){
|
||||
for (; g[idx] != idx; idx = g[idx] );
|
||||
return idx;
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < n; ++i ){
|
||||
for (size_t j = 0; j < m; ++j){
|
||||
if (board[i][j] == 'x'){
|
||||
if (j>0 && board[i][j-1] == 'x'){
|
||||
g[idx(i,j)]=g[idx(i,j-1)];
|
||||
if (i>0 && board[i-1][j] == 'x'){
|
||||
g[root(idx(i-1,j))]=g[idx(i,j)];
|
||||
}
|
||||
}
|
||||
else if (i>0 && board[i-1][j] == 'x'){
|
||||
g[idx(i,j)]=g[idx(i-1,j)];
|
||||
}
|
||||
else {
|
||||
g[idx(i,j)]=idx(i,j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for ( const auto& node: g){
|
||||
if ( node.first == node.second ){
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
|
||||
std::cout << number_of_islands({
|
||||
"xxxoo",
|
||||
"oooxx",
|
||||
"xxoox"
|
||||
}) << std::endl;
|
||||
|
||||
std::cout << number_of_islands({
|
||||
".xx..",
|
||||
"xx...",
|
||||
"xxxxx"
|
||||
}) << std::endl;
|
||||
std::cout << number_of_islands({
|
||||
"....x",
|
||||
"....x",
|
||||
"xxxxx"
|
||||
}) << std::endl;
|
||||
std::cout << number_of_islands({
|
||||
"xxxxx",
|
||||
"xxxxx",
|
||||
"xxxxx"
|
||||
}) << std::endl;
|
||||
std::cout << number_of_islands({
|
||||
"xxxxx",
|
||||
"....x",
|
||||
"xxx.x",
|
||||
"x...x",
|
||||
"xxxxx"
|
||||
}) << std::endl;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
|
||||
185
puzzles/training/old_mile.cpp
Normal file
185
puzzles/training/old_mile.cpp
Normal file
@@ -0,0 +1,185 @@
|
||||
O,1,11.3,4781,S, 1,5
|
||||
O,6,53.8,1589,S, 3,7
|
||||
O,4,40.7,9544,B, 5,9
|
||||
O,7,14.6,858,B, 6,10
|
||||
O,3,32.5,6971,S, 7,11
|
||||
O,5,19.5,8747,S, 7,11
|
||||
O,0,95.6,1206,S, 10,14
|
||||
O,2,57.5,2178,B, 11,15
|
||||
|
||||
|
||||
Q,1
|
||||
Q,6
|
||||
Q,10
|
||||
Q,12
|
||||
Q,14
|
||||
Q,14
|
||||
Q,15
|
||||
Q,15
|
||||
|
||||
|
||||
R,3384
|
||||
R,3384
|
||||
R,3384
|
||||
R,3384
|
||||
R,3384
|
||||
R,11133
|
||||
R,0
|
||||
R,16576
|
||||
|
||||
#include <cstdint>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Please disable before submitting.
|
||||
constexpr bool kDebug = false;
|
||||
|
||||
struct order {
|
||||
uint64_t order_token;
|
||||
uint64_t shares;
|
||||
double price;
|
||||
bool side; // false = sell, true = buy
|
||||
uint64_t created_at;
|
||||
uint64_t cancelled_or_executed_at;
|
||||
};
|
||||
|
||||
struct query {
|
||||
uint64_t query_time;
|
||||
};
|
||||
|
||||
std::vector<uint64_t> your_solution(const vector<order> &orders,
|
||||
const vector<query> &queries) {
|
||||
|
||||
std::vector<uint64_t> resp(queries.size(), 0);
|
||||
|
||||
std::vector<std::pair<query, size_t>> sorted_queries;
|
||||
sorted_queries.reserve(queries.size());
|
||||
for (size_t i = 0; i < queries.size(); ++i ){
|
||||
sorted_queries.emplace_back(queries[i],i);
|
||||
}
|
||||
std::sort(sorted_queries.begin(), sorted_queries.end(),
|
||||
[](const auto& op1, const auto& op2){
|
||||
return op1.first.query_time < op2.first.query_time;
|
||||
});
|
||||
|
||||
std::vector<order> sorted_orders(orders.begin(), orders.end());
|
||||
std::sort(sorted_orders.begin(), sorted_orders.end(),
|
||||
[](const auto& op1, const auto& op2){
|
||||
return op1.created_at < op2.created_at;
|
||||
});
|
||||
|
||||
std::vector<std::vector<order>::iterator> current_orders;
|
||||
auto current_orders_cmp = [](const auto& op1, const auto& op2){
|
||||
return op1->cancelled_or_executed_at < op2->cancelled_or_executed_at;
|
||||
};
|
||||
|
||||
|
||||
auto ot = sorted_orders.begin();
|
||||
for (const auto& q : sorted_queries){
|
||||
while ( !current_orders.empty()
|
||||
&& current_orders.front()->cancelled_or_executed_at < q.first.query_time){
|
||||
// remove from heap
|
||||
std::pop_heap(current_orders.begin(), current_orders.end(),
|
||||
current_orders_cmp);
|
||||
current_orders.resize(current_orders.size()-1);
|
||||
}
|
||||
|
||||
// std::cout << "2222222" << std::endl;
|
||||
|
||||
while (ot != sorted_orders.end() && ot->created_at <= q.first.query_time){
|
||||
if ( ot->cancelled_or_executed_at >= q.first.query_time){
|
||||
current_orders.push_back(ot);
|
||||
std::push_heap(current_orders.begin(), current_orders.end(),
|
||||
current_orders_cmp);
|
||||
}
|
||||
++ot;
|
||||
}
|
||||
|
||||
// std::cout << "33333" << std::endl;
|
||||
|
||||
uint64_t shares_live = 0;
|
||||
for (const auto cot : current_orders){
|
||||
shares_live += cot->shares;
|
||||
}
|
||||
resp[q.second] = shares_live;
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Please do not change any code below. //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::pair<vector<order>, vector<query>> gen_input(int seed) {
|
||||
mt19937 gen(seed);
|
||||
|
||||
const uint64_t order_len = 1 << (gen() % 20);
|
||||
const uint64_t time_len = 1 << (gen() % 20);
|
||||
|
||||
vector<order> orders;
|
||||
for (uint64_t i = 0; i < order_len; ++i) {
|
||||
const double duration = std::max(1.0, time_len / std::log2(time_len));
|
||||
const uint64_t start = gen() % time_len;
|
||||
const uint64_t end = std::min<int>(start + duration, time_len);
|
||||
order o{
|
||||
.order_token = i,
|
||||
.shares = static_cast<uint64_t>(gen() % 10000),
|
||||
.price = static_cast<double>(gen() % 1000) / 10,
|
||||
.side = gen() % 2 ? false : true,
|
||||
.created_at = start,
|
||||
.cancelled_or_executed_at = end,
|
||||
};
|
||||
orders.emplace_back(o);
|
||||
}
|
||||
|
||||
vector<query> queries;
|
||||
for (uint64_t i = 0; i < order_len; ++i) {
|
||||
query q{
|
||||
.query_time = static_cast<uint64_t>(gen() % time_len),
|
||||
};
|
||||
queries.emplace_back(q);
|
||||
}
|
||||
|
||||
return {std::move(orders), std::move(queries)};
|
||||
}
|
||||
|
||||
int hash_result(const std::vector<uint64_t> &answers) {
|
||||
std::hash<uint64_t> hasher;
|
||||
uint64_t result = 0;
|
||||
for (auto &a : answers) {
|
||||
result = hasher(a) ^ (result << 1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// This test harness generates an input to and hashes the output from your
|
||||
// solution. Please do not change any code below this line.
|
||||
int solution(int seed) {
|
||||
auto input = gen_input(seed);
|
||||
bool debug = kDebug && input.first.size() < 100 && input.second.size() < 100;
|
||||
if (debug) {
|
||||
for (auto &o : input.first) {
|
||||
std::cerr << "O," << o.order_token << "," << o.price << "," << o.shares
|
||||
<< "," << (o.side ? 'B' : 'S') << "," << o.created_at << ","
|
||||
<< o.cancelled_or_executed_at << "\n";
|
||||
}
|
||||
for (auto &q : input.second) {
|
||||
std::cerr << 'Q' << "," << q.query_time << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
const auto answers = your_solution(input.first, input.second);
|
||||
|
||||
if (debug) {
|
||||
for (auto &a : answers) {
|
||||
std::cerr << "R," << a << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return hash_result(answers);
|
||||
}
|
||||
|
||||
70
puzzles/training/permutation.cpp
Normal file
70
puzzles/training/permutation.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
VIM: let b:cf5build="clang++ -std=c++20 -O2 -pthread -I. {SRC} -o {OUT}"
|
||||
VIM: let b:cf5run="{OUT}"
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
|
||||
void permutate(auto b, auto e)
|
||||
{
|
||||
auto bt = std::reverse_iterator(e);
|
||||
auto et = std::reverse_iterator(b);
|
||||
|
||||
auto it = bt+1;
|
||||
for ( ; it != et && *it >= *(it-1); ++it);
|
||||
|
||||
for (auto qt = bt, rt = it-1; rt > qt; qt++, rt--){
|
||||
std::swap(*qt, *rt);
|
||||
}
|
||||
|
||||
if (it != et){
|
||||
auto pt = it-1;
|
||||
for( ; pt != bt && *it >= *pt; --pt);
|
||||
std::swap(*it, *pt);
|
||||
}
|
||||
}
|
||||
|
||||
void test(std::string char_set)
|
||||
{
|
||||
std::sort(char_set.begin(), char_set.end());
|
||||
std::string perm = char_set;
|
||||
int i = 0;
|
||||
do {
|
||||
++i;
|
||||
std::cout << perm << '\n';
|
||||
permutate(perm.begin(), perm.end());
|
||||
} while (perm != char_set);
|
||||
|
||||
std::cout << i << '\n' << "-------------------------------------\n";
|
||||
}
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
test( "abcd" );
|
||||
test( "aab" );
|
||||
test( "aabb" );
|
||||
test( "aaabbb" );
|
||||
|
||||
//......
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
|
||||
50
puzzles/training/permutation.py
Normal file
50
puzzles/training/permutation.py
Normal file
@@ -0,0 +1,50 @@
|
||||
def permutation(s, b, e):
|
||||
"""
|
||||
Prints all permutations.
|
||||
"""
|
||||
if b+1 == e:
|
||||
print(s)
|
||||
else:
|
||||
for i in range(b, e-1):
|
||||
permutation(s, b+1, e)
|
||||
c = s[i+1]
|
||||
s[i+1] = s[i]
|
||||
s[i] = s[b]
|
||||
s[b] = c
|
||||
permutation(s, b+1, e)
|
||||
c = s[b]
|
||||
s[b] = s[e-1]
|
||||
s[e-1] = c
|
||||
|
||||
|
||||
def permutation2(s):
|
||||
"""
|
||||
Prints all permutations. But in addition doesn't print
|
||||
multiple instances of same value.
|
||||
e.g. abb bab bba ( doesn't print two abb )
|
||||
"""
|
||||
print(s)
|
||||
l = len(s)
|
||||
|
||||
while True:
|
||||
i = l-1
|
||||
while True:
|
||||
ii = i
|
||||
i = i - 1
|
||||
if ord(s[i]) < ord(s[ii]):
|
||||
j = l-1
|
||||
while ord(s[i]) >= ord(s[j]):
|
||||
j = j - 1
|
||||
s[i], s[j] = s[j], s[i]
|
||||
s[ii:l] = s[ii:l][::-1]
|
||||
print(s)
|
||||
break
|
||||
if i == 0:
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
s = ['a', 'b', 'c', 'd', 'e', 'e']
|
||||
permutation(s, 0, len(s))
|
||||
print("--------------------------------------------")
|
||||
permutation2(s)
|
||||
80
puzzles/training/power_ap.cpp
Normal file
80
puzzles/training/power_ap.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
VIM: let b:lcppflags="-std=c++14 -O2 -pthread -I."
|
||||
VIM: let b:wcppflags="/O2 /EHsc /DWIN32"
|
||||
VIM-: let b:cppflags=g:Iboost.g:Itbb
|
||||
VIM-: let b:ldflags=g:Lboost.g:Ltbb
|
||||
VIM-: let b:ldlibpath=g:Bboost.g:Btbb
|
||||
VIM-: let b:argv=""
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
|
||||
/*
|
||||
* Given a positive integer which fits in a 32 bit signed integer, find if it
|
||||
* can be expressed as A^P where P > 1 and A > 0. A and P both should be
|
||||
* integers.
|
||||
*/
|
||||
|
||||
bool isPower(int X) {
|
||||
|
||||
if ( X == 1 ){
|
||||
return true;
|
||||
}
|
||||
|
||||
double log_X = std::log(X);
|
||||
long long end = log_X / std::log(2) +1;
|
||||
for ( int i = 2; i <= end; ++i ) {
|
||||
double A = std::exp(log_X/double(i));
|
||||
double rA = std::round(A);
|
||||
std::cout << "--> A=" << A << " r(" << rA << ") I=" << i << " diff=" << std::fabs(A-rA) << std::endl;
|
||||
if ( std::fabs(A-rA) < 0.00001 ) {
|
||||
int int_A = rA;
|
||||
std::cout << "Testing --> A=" << A << " r("<<int_A << ") I=" << i << std::endl;
|
||||
long long test = 1;
|
||||
for ( int j = 0; j < i; ++j ) {
|
||||
test *= int_A;
|
||||
}
|
||||
if ( test == X ) {
|
||||
std::cout << "X=" << X << " A=" << int_A << " I=" << i << std::endl;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << "X=" << X << " no power found." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
isPower(1);
|
||||
isPower(4);
|
||||
isPower(3);
|
||||
isPower(27);
|
||||
isPower(1024000000);
|
||||
isPower(1024*1024*1024);
|
||||
|
||||
//......
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
|
||||
98
puzzles/training/preorder_tree_construction.cpp
Normal file
98
puzzles/training/preorder_tree_construction.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
VIM: let b:lcppflags="-std=c++11 -O2 -pthread"
|
||||
VIM: let b:wcppflags="/O2 /EHsc /DWIN32"
|
||||
VIM: let b:argv=""
|
||||
*/
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <stack>
|
||||
#include <iostream>
|
||||
|
||||
struct node {
|
||||
node * left = nullptr;
|
||||
node * right = nullptr;
|
||||
double data = 0;
|
||||
|
||||
node( double d )
|
||||
: data(d)
|
||||
{}
|
||||
};
|
||||
|
||||
node * prefix_to_tree( const std::vector<double>& v ){
|
||||
|
||||
if ( !v.size() ){
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
node * root = new node(v[0]);
|
||||
|
||||
std::stack<node*> stack;
|
||||
stack.push(root);
|
||||
|
||||
for ( int i = 1; i < v.size(); ) {
|
||||
if ( v[i] < stack.top()->data ){
|
||||
auto n = new node(v[i++]);
|
||||
stack.top()->left = n;
|
||||
stack.push(n);
|
||||
} else {
|
||||
auto c = stack.top();
|
||||
stack.pop();
|
||||
while( !stack.empty() && stack.top()->data < v[i] ){
|
||||
c = stack.top();
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
auto n = new node(v[i++]);
|
||||
c->right = n;
|
||||
stack.push(n);
|
||||
}
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
void print( node * root, const std::string& level = "" ){
|
||||
if ( root ) {
|
||||
print( root->left, level + " ");
|
||||
std::cout << level << "- " << root->data << std::endl;
|
||||
print( root->right, level + " ");
|
||||
}
|
||||
}
|
||||
|
||||
void traverse( node * root, std::vector<double>& v ){
|
||||
if ( root ) {
|
||||
v.push_back(root->data);
|
||||
traverse(root->left, v);
|
||||
traverse(root->right, v);
|
||||
}
|
||||
}
|
||||
|
||||
void test( const std::vector<double>& v ){
|
||||
std::cout << "-----------------------------------------------------" << std::endl;
|
||||
auto r = prefix_to_tree( v );
|
||||
print( r );
|
||||
std::vector<double> w;
|
||||
traverse( r, w );
|
||||
if ( v.size() != w.size() ) {
|
||||
std::cout << "v.size() != w.size() => " << v.size() << " != " << w.size() << std::endl;
|
||||
}
|
||||
for (int i = 0; i < v.size(); ++i ){
|
||||
if (v[i]!=w[i]){
|
||||
std::cout << "error at index " << i << " -> "<< v[i] << " != " << w[i] << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main( void ) {
|
||||
|
||||
test( {1} );
|
||||
test( {2, 1, 3} );
|
||||
test( {4, 2, 1, 3, 6, 5, 7} );
|
||||
test( {8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15} );
|
||||
test( {8, 4, 2, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15} );
|
||||
test( {8, 4, 6, 5, 7, 12, 10, 9, 14, 13, 15} );
|
||||
test( {8, 12, 10, 9, 11, 14, 13, } );
|
||||
test( {8, 4, 2, 1, 6, 12, 10, 11, 14, 15} );
|
||||
|
||||
return 0;
|
||||
}
|
||||
41
puzzles/training/print_max_evenly.py
Normal file
41
puzzles/training/print_max_evenly.py
Normal file
@@ -0,0 +1,41 @@
|
||||
import random
|
||||
|
||||
|
||||
#
|
||||
# You have a array with integers: e.g. [ 1, -2, 0, 6, 2, -4, 6, 6 ]
|
||||
# You need to write a function which will evenly return indexes of a
|
||||
# max value in the array.
|
||||
# In the example above max value is 6, and its positions are 3, 6 and 7.
|
||||
# So each run function should return random index from the set.
|
||||
#
|
||||
# Try to implement with O(n) for computation and memory.
|
||||
# Try to reduce memory complexity to O(1).
|
||||
#
|
||||
def return_max_evenly(arr):
|
||||
mv = float('-inf')
|
||||
mi = -1
|
||||
mc = 0
|
||||
for i in range(len(arr)):
|
||||
if mv < arr[i]:
|
||||
mv = arr[i]
|
||||
mi = i
|
||||
mc = 1
|
||||
elif mv == arr[i]:
|
||||
mc = mc + 1
|
||||
if random.random() < 1./mc:
|
||||
mi = i
|
||||
if mi != -1:
|
||||
return mi
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
random.seed()
|
||||
arr = [1, -2, 0, 6, 2, -4, 6, 6]
|
||||
ret = {}
|
||||
for i in range(10000):
|
||||
r = return_max_evenly(arr)
|
||||
if r in ret:
|
||||
ret[r] = ret[r] + 1
|
||||
else:
|
||||
ret[r] = 1
|
||||
print(ret)
|
||||
95
puzzles/training/simple_wildcard_match.cpp
Normal file
95
puzzles/training/simple_wildcard_match.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
VIM: let b:lcppflags="-std=c++14 -O2 -pthread -I."
|
||||
VIM: let b:wcppflags="/O2 /EHsc /DWIN32"
|
||||
VIM-: let b:cppflags=g:Iboost.g:Itbb
|
||||
VIM-: let b:ldflags=g:Lboost.g:Ltbb
|
||||
VIM-: let b:ldlibpath=g:Bboost.g:Btbb
|
||||
VIM-: let b:argv=""
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
|
||||
/*
|
||||
Simple wildcard match.
|
||||
|
||||
*/
|
||||
|
||||
bool wildcard_match(const std::string& input, const std::string& pattern)
|
||||
{
|
||||
int j = 0;
|
||||
int i = 0;
|
||||
int restart_idx = -1;
|
||||
while ( i < input.size() )
|
||||
{
|
||||
while ( j < pattern.size() && pattern[j] == '*' ){
|
||||
restart_idx = ++j;
|
||||
}
|
||||
if ( j<pattern.size() && pattern[j] == input[i] ) {
|
||||
++i;
|
||||
++j;
|
||||
}
|
||||
else if ( j>= 0 && pattern[j-1] == '*' ) {
|
||||
++i;
|
||||
}
|
||||
else if ( restart_idx > 0 ) {
|
||||
i -= j - restart_idx -1;
|
||||
j = restart_idx;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while ( j < pattern.size() && pattern[j] == '*' ){
|
||||
++j;
|
||||
}
|
||||
return j == pattern.size();
|
||||
}
|
||||
|
||||
void test(const std::string& input, const std::string& pattern)
|
||||
{
|
||||
std::cout << input << " x " << pattern
|
||||
<< " == " << wildcard_match(input,pattern)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
test("zebra", "dog");
|
||||
test("zebra", "zebra");
|
||||
test("zebra", "*br*");
|
||||
test("zebra", "*bi*");
|
||||
test("zebra", "*br*a");
|
||||
test("zebra", "*br*b");
|
||||
test("zebra", "z**a");
|
||||
test("zebra", "z*a");
|
||||
test("zebra", "x**a");
|
||||
test("zebrabrb", "*brb*");
|
||||
test("zebra", "*bra*");
|
||||
test("zebrazebrazebra", "*bra*zeb*zeb*");
|
||||
test("zebrbzebrazebra", "*bra*zeb*zeb*");
|
||||
test("zebrbzebrazebra", "*bra*zeb*");
|
||||
test("zebrbzebrazebra", "*****bra*zeb*****");
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
|
||||
106
puzzles/training/stepping_number.cpp
Normal file
106
puzzles/training/stepping_number.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
VIM: let b:lcppflags="-std=c++14 -O2 -pthread -I."
|
||||
VIM: let b:wcppflags="/O2 /EHsc /DWIN32"
|
||||
VIM-: let b:cppflags=g:Iboost.g:Itbb
|
||||
VIM-: let b:ldflags=g:Lboost.g:Ltbb
|
||||
VIM-: let b:ldlibpath=g:Bboost.g:Btbb
|
||||
VIM-: let b:argv=""
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/*Given N and M find all stepping numbers in range N to M
|
||||
|
||||
The stepping number:
|
||||
|
||||
A number is called as a stepping number if the adjacent digits have a difference of 1.
|
||||
e.g 123 or 101 is stepping number, but 358 is not a stepping number
|
||||
|
||||
Example:
|
||||
|
||||
N = 10, M = 20
|
||||
all stepping numbers are 10 , 12
|
||||
|
||||
Return the numbers in sorted order.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Solution: complexity is linear actually. O(n)
|
||||
* So, a better solution I guess will be to interate over the range
|
||||
* and check each number on condition.
|
||||
*/
|
||||
|
||||
|
||||
void f( std::vector<int>& v, int A, int B, int n )
|
||||
{
|
||||
if ( A <= n && n <= B ) {
|
||||
v.push_back(n);
|
||||
}
|
||||
else if ( n > B ) {
|
||||
return;
|
||||
}
|
||||
|
||||
int d = n % 10;
|
||||
if ( d + 1 <= 9 ){
|
||||
f( v, A, B, n*10+d+1);
|
||||
}
|
||||
if ( d - 1 >= 0 ){
|
||||
f( v, A, B, n*10+d-1);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int> stepnum(int A, int B)
|
||||
{
|
||||
std::vector<int> v;
|
||||
|
||||
if ( A <= 0 && 0 <= B ){
|
||||
v.push_back(0);
|
||||
}
|
||||
|
||||
for ( int i = 1; i <= 9; ++i ){
|
||||
f( v, A, B, i );
|
||||
}
|
||||
|
||||
std::sort(v.begin(), v.end());
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
void print( const std::vector<int>& A )
|
||||
{
|
||||
for (auto i: A){
|
||||
std::cout << i << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
|
||||
//......
|
||||
print( stepnum(10, 20) );
|
||||
print( stepnum(0, 1000) );
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
|
||||
84
puzzles/training/string_addition.cpp
Normal file
84
puzzles/training/string_addition.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
VIM: let b:lcppflags="-std=c++14 -O2 -pthread -I."
|
||||
VIM: let b:wcppflags="/O2 /EHsc /DWIN32"
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <atomic>
|
||||
|
||||
/*
|
||||
given an array representing a non-negative integer (ex: 123 represented
|
||||
as [1,2,3]), return the next integer (output: [1,2,4]).
|
||||
run through all edge cases (ex: [9,9,9,9,9,9,9,9] etc)
|
||||
*/
|
||||
|
||||
int dig(char ch) {
|
||||
return ch - '0';
|
||||
}
|
||||
|
||||
char chr(int dig) {
|
||||
return dig + '0';
|
||||
}
|
||||
|
||||
std::string incr(std::string n) {
|
||||
int carry = 1;
|
||||
for (size_t i = n.size(); i-- > 0; ) {
|
||||
int ds = dig(n[i]) + carry;
|
||||
if (ds >= 10) {
|
||||
carry = ds / 10;
|
||||
ds %= 10;
|
||||
}
|
||||
else {
|
||||
carry = 0;
|
||||
}
|
||||
n[i] = chr(ds);
|
||||
}
|
||||
|
||||
if (carry) {
|
||||
return chr(carry) + n;
|
||||
}
|
||||
else {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try {
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::cout << incr("0") << std::endl;
|
||||
std::cout << incr("1") << std::endl;
|
||||
std::cout << incr("9") << std::endl;
|
||||
std::cout << incr("10") << std::endl;
|
||||
std::cout << incr("15") << std::endl;
|
||||
std::cout << incr("19") << std::endl;
|
||||
std::cout << incr("99") << std::endl;
|
||||
std::cout << incr("9999999") << std::endl;
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
74
puzzles/training/subset_min_max_count.cpp
Normal file
74
puzzles/training/subset_min_max_count.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
VIM: let b:lcppflags="-std=c++14 -O2 -pthread -I."
|
||||
VIM: let b:wcppflags="/O2 /EHsc /DWIN32"
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
/*
|
||||
google-interview-questions
|
||||
For a given vector of integers and integer K, find the number of non-empty subsets S such that min(S) + max(S) <= K
|
||||
For example, for K = 8 and vector [2, 4, 5, 7], the solution is 5 ([2], [4], [2, 4], [2, 4, 5], [2, 5])
|
||||
The time complexity should be O(n2). Approach and code was asked
|
||||
*/
|
||||
|
||||
int countSubsets(std::vector<int> numbers, int k)
|
||||
{
|
||||
int total_sum = 0;
|
||||
for (int i = 0; i < numbers.size(); ++i) {
|
||||
|
||||
if (2 * numbers[i] > k) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int sum = 1;
|
||||
int max = numbers[i];
|
||||
int min = numbers[i];
|
||||
for (int j = i+1; j < numbers.size(); ++j) {
|
||||
int tmp_max = std::max(max, numbers[j]);
|
||||
int tmp_min = std::min(min, numbers[j]);
|
||||
|
||||
if (tmp_max + tmp_min <= k) {
|
||||
sum *= 2;
|
||||
min = tmp_min;
|
||||
max = tmp_max;
|
||||
}
|
||||
}
|
||||
total_sum += sum;
|
||||
}
|
||||
|
||||
return total_sum;
|
||||
}
|
||||
|
||||
int main()
|
||||
{try{
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
|
||||
//......
|
||||
std::cout << countSubsets({ 2, 4, 5, 7 }, 8) << std::endl;
|
||||
|
||||
|
||||
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
107
puzzles/training/unique_prefix.cpp
Normal file
107
puzzles/training/unique_prefix.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
VIM: let b:lcppflags="-std=c++14 -O2 -pthread -I."
|
||||
VIM: let b:wcppflags="/O2 /EHsc /DWIN32"
|
||||
VIM-: let b:cppflags=g:Iboost.g:Itbb
|
||||
VIM-: let b:ldflags=g:Lboost.g:Ltbb
|
||||
VIM-: let b:ldlibpath=g:Bboost.g:Btbb
|
||||
VIM-: let b:argv=""
|
||||
*/
|
||||
#include <iostream>
|
||||
#include <exception>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
/*
|
||||
PREFIX
|
||||
|
||||
Find shortest unique prefix to represent each word in the list.
|
||||
|
||||
Example:
|
||||
|
||||
Input: [zebra, dog, duck, dove]
|
||||
Output: {z, dog, du, dov}
|
||||
where we can see that
|
||||
zebra = z
|
||||
dog = dog
|
||||
duck = du
|
||||
dove = dov
|
||||
|
||||
NOTE : Assume that no word is prefix of another. In other words, the
|
||||
representation is always possible.
|
||||
|
||||
*/
|
||||
|
||||
std::string get_prefix(const std::string& p1, const std::string& p2){
|
||||
for ( int i = 0; i < p1.size() && i < p2.size(); ++i){
|
||||
if ( p1[i] != p2[i] ){
|
||||
return p1.substr(0,i+1);
|
||||
}
|
||||
}
|
||||
return p1;
|
||||
}
|
||||
|
||||
std::vector<std::string> prefix(const std::vector<std::string> &A) {
|
||||
// Do not write main() function.
|
||||
// Do not read input, instead use the arguments to the function.
|
||||
// Do not print the output, instead return values as specified
|
||||
// Still have a doubt. Checkout www.interviewbit.com/pages/sample_codes/ for more details
|
||||
|
||||
std::vector<std::string> ret(A.size());
|
||||
|
||||
std::vector<int> B(A.size());
|
||||
for ( size_t i = 0; i < A.size(); ++i){
|
||||
B[i] = i;
|
||||
}
|
||||
std::sort(B.begin(), B.end(), [&A](int op1, int op2){
|
||||
return A[op1] < A[op2];
|
||||
});
|
||||
|
||||
for (int i = 0; i < B.size(); ++i){
|
||||
std::string p;
|
||||
if ( i-1 >= 0 ) {
|
||||
p = get_prefix(A[B[i]],A[B[i-1]]);
|
||||
}
|
||||
if ( i+1 < A.size() ){
|
||||
auto _p = get_prefix(A[B[i]],A[B[i+1]]);
|
||||
if ( _p.size() > p.size() ) {
|
||||
p = _p;
|
||||
}
|
||||
}
|
||||
if ( p.empty() ) {
|
||||
p = A[B[i]].substr(0,1);
|
||||
}
|
||||
ret[B[i]] = p;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int main ( void )
|
||||
{try{
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto p = prefix({"zebra", "dog", "duck", "dove"});
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double> seconds = end - begin;
|
||||
std::cout << "Time: " << seconds.count() << std::endl;
|
||||
for ( const auto& _p : p) {
|
||||
std::cout << _p << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
catch ( const std::exception& e )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "std::exception(\"" << e.what() << "\")." << std::endl;
|
||||
return 2;
|
||||
}
|
||||
catch ( ... )
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "unknown exception." << std::endl;
|
||||
return 1;
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user