Hello!
Welcome to Alex K's portfolio site. Below you can find a bunch of sections with samples of my work. Those marked with (WIP) means that Work In Progress, and it has not been finished yet, but if you have enough courage, you can glimpse inside. 😊
Business Systems Analyst (BSA)
OrderWeb
BSA portfolio project artifacts
In this document you can find group of artifacts that were created at the end of the first Business Systems Analyst interview session with Stakeholders on a future project.
Project documentations for the Mate Project - (WIP)
Mate (M7; M8; MAY7; mt; MT) project documentations.
P2P space for interactions with your flatmates.
Backbone ideas:
- booking into shared calendar for shared space, instruments, tools;
- Democratic approval for used of shared things and booking it;
- Distribution of shared responsibilities & tasks;
- Messaging;
- File exchange;
- Possibly calls
NB The Project in its early stages and flagged as Work In Progress.
Tech stack (most probably) would be:
- Rust;
- Diesel (postgres ?);
- JavaScript;
- React.js
Python
r0-bot-U_trebA (WIP)
- README.md
- solution r0-bot-u_treba.py
- requirements requirements.txt
description:
Extension & Automation tool for LinkedIn users, based on the headless Selenium.
This tool is aiming to improve your experience of building up a connections network on the LinkedIn platform in ethical way and try to avoid violation of the User Agreement. This tool will help you to expand your network, by mimicking natural users' behaviour with randomized delays between the interactions with the site and stay within the platform's limits, so you wouldn't face restrictions for your account.
Rust
Handpicked highlights that I've most enjoyed solving
Affine Cipher
- README.md
- solution src/lib.rs
description:
Create an implementation of the affine cipher, an ancient encryption system created in the Middle East.
The affine cipher is a type of monoalphabetic substitution cipher. Each character is mapped to its numeric equivalent, encrypted with a mathematical function and then converted to the letter relating to its new numeric value. Although all monoalphabetic ciphers are weak, the affine cypher is much stronger than the atbash cipher, because it has many more keys.
The encryption function is:
E(x) = (ax + b) mod m
- where x
is the letter's index from 0 - length of alphabet - 1
- m
is the length of the alphabet. For the roman alphabet m == 26
.
- and a
and b
make the key
The decryption function is:
D(y) = a^-1(y - b) mod m
- where y
is the numeric value of an encrypted letter, ie. y = E(x)
- it is important to note that a^-1
is the modular multiplicative inverse
of a mod m
- the modular multiplicative inverse of a
only exists if a
and m
are
coprime.
To find the MMI of a
:
an mod m = 1
- where n
is the modular multiplicative inverse of a mod m
More information regarding how to find a Modular Multiplicative Inverse and what it means can be found here.
Because automatic decryption fails if a
is not coprime to m
your
program should return status 1 and "Error: a and m must be coprime."
if they are not. Otherwise it should encode or decode with the
provided key.
The Caesar (shift) cipher is a simple affine cipher where a
is 1 and
b
as the magnitude results in a static displacement of the letters.
This is much less secure than a full implementation of the affine cipher.
Ciphertext is written out in groups of fixed length, the traditional group size being 5 letters, and punctuation is excluded. This is to make it harder to guess things based on word boundaries.
General Examples
- Encoding
test
givesybty
with the key a=5 b=7 - Decoding
ybty
givestest
with the key a=5 b=7 - Decoding
ybty
giveslqul
with the wrong key a=11 b=7 - Decoding
kqlfd jzvgy tpaet icdhm rtwly kqlon ubstx
- gives
thequickbrownfoxjumpsoverthelazydog
with the key a=19 b=13 - Encoding
test
with the key a=18 b=13 - gives
Error: a and m must be coprime.
- because a and m are not relatively prime
Examples of finding a Modular Multiplicative Inverse (MMI)
- simple example:
9 mod 26 = 9
9 * 3 mod 26 = 27 mod 26 = 1
3
is the MMI of9 mod 26
- a more complicated example:
15 mod 26 = 15
15 * 7 mod 26 = 105 mod 26 = 1
7
is the MMI of15 mod 26
Based on
Wikipedia - https://en.wikipedia.org/wiki/Affine_cipher
Run-Length Encoding
- README.md
- solution src/lib.rs
description:
Implement run-length encoding and decoding.
Run-length encoding (RLE) is a simple form of data compression, where runs (consecutive data elements) are replaced by just one data value and count.
For example we can represent the original 53 characters with only 13.
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB" -> "12WB12W3B24WB"
RLE allows the original data to be perfectly reconstructed from the compressed data, which makes it a lossless data compression.
"AABCCCDEEEE" -> "2AB3CD4E" -> "AABCCCDEEEE"
Based on
Wikipedia - https://en.wikipedia.org/wiki/Run-length_encoding
Atbash Cipher
- README.md
- solution src/lib.rs
description:
Create an implementation of the atbash cipher, an ancient encryption system created in the Middle East.
The Atbash cipher is a simple substitution cipher that relies on transposing all the letters in the alphabet such that the resulting alphabet is backwards. The first letter is replaced with the last letter, the second with the second-last, and so on.
An Atbash cipher for the Latin alphabet would be as follows:
Plain: abcdefghijklmnopqrstuvwxyz
Cipher: zyxwvutsrqponmlkjihgfedcba
It is a very weak cipher because it only has one possible key, and it is a simple mono-alphabetic substitution cipher. However, this may not have been an issue in the cipher's time.
Ciphertext is written out in groups of fixed length, the traditional group size being 5 letters, and punctuation is excluded. This is to make it harder to guess things based on word boundaries.
Examples
- Encoding
test
givesgvhg
- Decoding
gvhg
givestest
- Decoding
gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt
givesthequickbrownfoxjumpsoverthelazydog
Based on
Wikipedia - https://en.wikipedia.org/wiki/Atbash
Rotational Cipher aka Caesar cipher
- README.md
- solution src/lib.rs
description:
Create an implementation of the rotational cipher, also sometimes called the Caesar cipher.
The Caesar cipher is a simple shift cipher that relies on
transposing all the letters in the alphabet using an integer key
between 0
and 26
. Using a key of 0
or 26
will always yield
the same output due to modular arithmetic. The letter is shifted
for as many values as the value of the key.
The general notation for rotational ciphers is ROT + <key>
.
The most commonly used rotational cipher is ROT13
.
A ROT13
on the Latin alphabet would be as follows:
Plain: abcdefghijklmnopqrstuvwxyz
Cipher: nopqrstuvwxyzabcdefghijklm
It is stronger than the Atbash cipher because it has 27 possible keys, and 25 usable keys.
Ciphertext is written out in the same formatting as the input including spaces and punctuation.
Examples
- ROT5
omg
givestrl
- ROT0
c
givesc
- ROT26
Cool
givesCool
- ROT13
The quick brown fox jumps over the lazy dog.
givesGur dhvpx oebja sbk whzcf bire gur ynml qbt.
- ROT13
Gur dhvpx oebja sbk whzcf bire gur ynml qbt.
givesThe quick brown fox jumps over the lazy dog.
Based on
Wikipedia - https://en.wikipedia.org/wiki/Caesar_cipher
Luhn algorithm
- README.md
- solution src/lib.rs
description:
Given a number determine whether or not it is valid per the Luhn formula.
The Luhn algorithm is a simple checksum formula used to validate a variety of identification numbers, such as credit card numbers and Canadian Social Insurance Numbers.
The task is to check if a given string is valid.
Validating a Number
Strings of length 1 or less are not valid. Spaces are allowed in the input, but they should be stripped before checking. All other non-digit characters are disallowed.
Example 1: valid credit card number
4539 3195 0343 6467
The first step of the Luhn algorithm is to double every second digit, starting from the right. We will be doubling
4_3_ 3_9_ 0_4_ 6_6_
If doubling the number results in a number greater than 9 then subtract 9 from the product. The results of our doubling:
8569 6195 0383 3437
Then sum all the digits:
8+5+6+9+6+1+9+5+0+3+8+3+3+4+3+7 = 80
If the sum is evenly divisible by 10, then the number is valid. This number is valid!
Example 2: invalid credit card number
8273 1232 7352 0569
Double the second digits, starting from the right
7253 2262 5312 0539
Sum the digits
7+2+5+3+2+2+6+2+5+3+1+2+0+5+3+9 = 57
57 is not evenly divisible by 10, so this number is not valid.
Based on
The Luhn Algorithm on Wikipedia - https://en.wikipedia.org/wiki/Luhn_algorithm
Poker
- README.md
- solution src/lib.rs
description:
Pick the best hand(s) from a list of poker hands.
See wikipedia for an overview of poker hands.
- Ranking a list of poker hands can be considered a sorting problem.
- Rust provides the sort method for
Vec<T> where T: Ord
. Ord
types form a total order: exactly one ofa < b
,a == b
, ora > b
must be true.- Poker hands do not conform to a total order: it is possible for two hands to be non-equal but have equal sort order. Example:
"3S 4S 5D 6H JH"
,"3H 4H 5C 6C JD"
. - Rust provides the
PartialOrd
trait to handle the case of sortable things which do not have a total order. However, it doesn't provide a standardsort
method forVec<T> where T: PartialOrd
. The standard idiom to sort a vector in this case isyour_vec.sort_by(|a, b| a.partial_cmp(b).unwrap_or(Ordering::{Less|Equal|Greater}));
, depending on your needs. - You might consider implementing a type representing a poker hand which implements
PartialOrd
.
Scale Generator
- README.md
- solution src/lib.rs
description:
Given a tonic, or starting note, and a set of intervals, generate
the musical scale starting with the tonic and following the
specified interval pattern.
Scales in Western music are based on the chromatic (12-note) scale. This scale can be expressed as the following group of pitches:
A, A#, B, C, C#, D, D#, E, F, F#, G, G#
A given sharp note (indicated by a #) can also be expressed as the flat of the note above it (indicated by a b) so the chromatic scale can also be written like this:
A, Bb, B, C, Db, D, Eb, E, F, Gb, G, Ab
The major and minor scale and modes are subsets of this twelve-pitch collection. They have seven pitches, and are called diatonic scales. The collection of notes in these scales is written with either sharps or flats, depending on the tonic. Here is a list of which are which:
No Sharps or Flats:
C major
a minor
Use Sharps:
G, D, A, E, B, F# major
e, b, f#, c#, g#, d# minor
Use Flats:
F, Bb, Eb, Ab, Db, Gb major
d, g, c, f, bb, eb minor
The diatonic scales, and all other scales that derive from the chromatic scale, are built upon intervals. An interval is the space between two pitches.
The simplest interval is between two adjacent notes, and is called a "half step", or "minor second" (sometimes written as a lower-case "m"). The interval between two notes that have an interceding note is called a "whole step" or "major second" (written as an upper-case "M"). The diatonic scales are built using only these two intervals between adjacent notes.
Non-diatonic scales can contain other intervals. An "augmented second" interval, written "A", has two interceding notes (e.g., from A to C or Db to E) or a "whole step" plus a "half step". There are also smaller and larger intervals, but they will not figure into this exercise.
Simple Cipher
- README.md
- solution src/lib.rs
description:
Implement a simple shift cipher like Caesar and a more secure substitution cipher.
Step 1
"If he had anything confidential to say, he wrote it in cipher, that is, by so changing the order of the letters of the alphabet, that not a word could be made out. If anyone wishes to decipher these, and get at their meaning, he must substitute the fourth letter of the alphabet, namely D, for A, and so with the others." —Suetonius, Life of Julius Caesar
Ciphers are very straight-forward algorithms that allow us to render text less readable while still allowing easy deciphering. They are vulnerable to many forms of cryptanalysis, but we are lucky that generally our little sisters are not crypt-analysts.
The Caesar Cipher was used for some messages from Julius Caesar that were sent afield. Now Caesar knew that the cipher wasn't very good, but he had one ally in that respect: almost nobody could read well. So even being a couple letters off was sufficient so that people couldn't recognize the few words that they did know.
Your task is to create a simple shift cipher like the Caesar Cipher. This image is a great example of the Caesar Cipher:
For example:
Giving iamapandabear
as input to the encode function returns the cipher ldpdsdqgdehdu
. Obscure enough to keep our message secret in transit.
When ldpdsdqgdehdu
is put into the decode function it would return
the original iamapandabear
letting your friend read your original
message.
Step 2
Shift ciphers are no fun though when your kid sister figures it out. Try amending the code to allow us to specify a key and use that for the shift distance. This is called a substitution cipher.
Here's an example:
Given the key aaaaaaaaaaaaaaaaaa
, encoding the string iamapandabear
would return the original iamapandabear
.
Given the key ddddddddddddddddd
, encoding our string iamapandabear
would return the obscured ldpdsdqgdehdu
In the example above, we've set a = 0
for the key value. So when the
plaintext is added to the key, we end up with the same message coming
out. So aaaa
is not an ideal key. But if we set the key to dddd
, we
would get the same thing as the Caesar Cipher.
Step 3
The weakest link in any cipher is the human being. Let's make your substitution cipher a little more fault-tolerant by providing a source of randomness and ensuring that the key contains only lowercase letters.
If someone doesn't submit a key at all, generate a truly random key of at least 100 lowercase characters in length.
Based on
Substitution Cipher at Wikipedia - http://en.wikipedia.org/wiki/Substitution_cipher
Nth Prime
- README.md
- solution src/lib.rs
description:
Given a number n, determine what the nth prime is.
By listing the first six prime numbers: 2, 3, 5, 7, 11, 13
, we can see that
the 6th prime is 13.
If your language provides methods in the standard library to deal with prime numbers, pretend they don't exist and implement them yourself.
Remember that while people commonly count with 1-based indexing (i.e. "the 6th prime is 13"), many programming languages, including Rust, use 0-based indexing (i.e. primes[5] == 13
).
Use 0-based indexing for your implementation.
Based on
A variation on Problem 7 at Project Euler - https://projecteuler.net/problem=7
All my Solved Exercism training exercises
- all of them on my Exercism
- or repo on my GitLab