interviews/training->training
This commit is contained in:
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}}
|
||||
|
||||
172
puzzles/training/diagonal.cpp
Normal file
172
puzzles/training/diagonal.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
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>
|
||||
#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;
|
||||
}}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}}
|
||||
|
||||
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;
|
||||
}}
|
||||
|
||||
103
puzzles/training/preorder_tree_construction.cpp
Normal file
103
puzzles/training/preorder_tree_construction.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
struct node {
|
||||
node * root = nullptr;
|
||||
node * left = nullptr;
|
||||
node * right = nullptr;
|
||||
double data = 0;
|
||||
|
||||
node( double d, node * r = nullptr )
|
||||
: root(r)
|
||||
, data(d)
|
||||
{}
|
||||
};
|
||||
|
||||
node * prefix_to_tree( const std::vector<double>& v ){
|
||||
|
||||
if ( !v.size() ){
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
node * root = new node(v[0]);
|
||||
node * current = root;
|
||||
node * max_node = nullptr;
|
||||
|
||||
for ( int i = 1; i < v.size(); ) {
|
||||
if ( v[i] < current->data ){
|
||||
max_node = current;
|
||||
current = new node(v[i++],current);
|
||||
current->root->left = current;
|
||||
} else if ( !max_node
|
||||
|| v[i] < max_node->data ){
|
||||
current = new node(v[i++],current);
|
||||
current->root->right = current;
|
||||
} else if ( current->root ){
|
||||
current = current->root;
|
||||
while ( max_node
|
||||
&& max_node->data <= current->data ) {
|
||||
node * tmp = max_node;
|
||||
max_node = max_node->root;
|
||||
if ( max_node && tmp == max_node->left ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::cout << "error" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !current || !root ) {
|
||||
std::cout << "errrrrrror" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << root << std::endl;
|
||||
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 ){
|
||||
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