An APL a day! - Put It In Reverse
Without much ado, today’s problem - Put it in Reverse The find function X⍷Y identifies the beginnings of occurrences of array X in array Y. In this problem, you’re asked to return a result that identifies the endings of occurrences of array X in array Y. To keep things simple, X and Y will be at most rank 1, meaning they’ll either be vectors or scalars. Write a function that: takes a scalar or vector left argument takes a scalar or vector right argument returns a Boolean result that is the same shape as the right argument where 1’s mark the ends of occurrences of the left argument in the right argument Examples: 'abra' findEnd 'abracadabra' 0 0 0 1 0 0 0 0 0 0 1 'issi' findEnd 'Mississippi' 0 0 0 0 1 0 0 1 0 0 0 'bb' findEnd 'bbb bbb' 0 1 1 0 0 1 1 (,42) findEnd 42 0 42 findEnd 42 1 (,42) findEnd ,42 1 'are' 'aquatic' findEnd 'ducks' 'are' 'aquatic' 'avians' 0 0 1 0 Solution See the solution {⌽(⌽⍺)⍷⌽⍵} We use ⍷ to find beginning of reversed array ⌽⍺ in ⌽⍵ We reverse this to get the ending of ⍺ in ⍵ Taking example 'abra' {⌽(⌽⍺)⍷⌽⍵} 'abracadabra' ...
An APL a day! - Elimination Sort
I’ve started dabbling with APL. It has been a lot of fun solving the current batch of challenges. Archive. I loved how each challenge focuses on a small set of operators and makes us use them in various (devious!) combinations to solve the problems. I’m going through some of the older challenges to learn about more operators. The past challenges can be found at APL Quest. Today, we’ll be solving the first problem from the 2023 challenge. Use tryapl.org as an online interactive REPL. Elimination Sort An “Elimination Sort” is a somewhat farcical sorting algorithm which starts with the leftmost element and keeps subsequent elements that are at least as large as the previous kept element, discarding all other elements. For example: EliminationSort 1 3 7 3 5 8 5 8 1 6 1 8 1 10 8 4 3 4 1 4 1 3 7 8 8 8 10 Write a function that: takes a non-empty numeric vector right argument returns an “Elimination-sorted” vector of the right argument Hint: The progressive-maxima idiomatic phrase ⌈, the greater or equal function ≥, and the replicate function / could be helpful in solving this problem. ...
Re-learning Lua
Lua - Basics for x = 0, 10, 1 do print(x) end -- for loop with range and step. step if not given is assumed to be 1 -- Tables are the soul of Lua. They double up as arrays and hashes a = {} b = {1, 2, 3} b[1] -- b[1] will return 1 as indexing for arrays is from 1 c = {[0]={123,3},["a"]={1,2,3},v={2,6,7}} -- We can have a "0"th index by adding the 1st element as [0]=value -- Adding keys which are not valid identifiers in Lua needs to be done by wrapping key in [] -- If a key is a valid identifier, we can access using `.` e.g c.a for above code vs c[0] for k,v in pairs(c) do print(type(k)) end -- iterates through k/v in table and prints type of key Print a table as valid Lua code function printTable(tbl) -- Specify function vars as local else they become global local s = "{" local fst = true for k,v in pairs(tbl) do local tk = type(k) local tv = type(v) if not fst then s = s .. "," else fst = false end if tk == "number" or tk == "boolean" then s = s .. "[" .. tostring(k) .. "]=" else s = s .. '["' .. k .. '"]=' end if tv == "table" then s = s .. printTable(v) elseif tv == "number" or tv == "boolean" then s = s .. tostring(v) elseif tv == "string" then s = s .. '"' .. v .. '"' else s = s .. vt end end s = s .. "}" return s end sv = printTable({[0]={123,3},["a"]={1,2,3},v={2,6,7},[true]=123}) print(sv) -- posts.lua (saved table) can be read from another lua file as posts=require("posts") return {[0]={[1]=123,[2]=3},["v"]={[1]=2,[2]=6,[3]=7},["a"]={[1]=1,[2]=2,[3]=3},[true]=123}
S3 Game
Introduction The best way to learn a skill is through deliberate practice! S3 Game is an awesome game made by Vasily Pantyukhin which walks you through various features of S3 from beginner to fairly advanced. What you will need: A browser aws cli CLICK HERE TO PLAY! Each level consists of finding a “treasure” object and getting to the next level using the secret code in the “treasure”. Go ahead and play this game. Each level contains multiple hints with links to S3 API documentation. Below is a walk through you can refer to if you are stuck on any level. Make sure that you try for a bit before seeing here :) Walk through (Spoilers) See the solution Level 1 Solution: # List the objects in bucket aws s3 ls s3://s3game-level1 Visit the treasure object Level 2 Solution: Just get the treasure2 object either using browser or aws s3 : https://s3game-level2.s3.us-east-2.amazonaws.com/treasure2 Make sure to save the Access and Secret key somewhere Level 3 Create an AWS profile “tmp” with the access and secret key obtained from previous level. You will need to use this for almost every level from here on. ...
NPM and Node tips to make your dev machine (slightly) safer
NPM is used as a convenient cross-platform package manager for a lot of developer tools. For many tools, the defacto way to install is npm install -g $TOOL. But installing anything via npm allows it to run untrusted code on your machine. Here are a few tips to minimize the risk: 1. NEVER run npm as sudo/root Node’s official documentation recommends not installing global packages as sudo/root. If you have already installed node through nvm ignore this step. If you use a system installed node e.g using Ubuntu’s apt-get, read through this guide for Linux/Mac or npm-g-nosudo which is a shell script for Linux. If you are lazy (like me), here’s a summary from the linked guide: mkdir -p "${HOME}/.npm-packages" && npm config set prefix "${HOME}/.npm-packages" Add this to your .bashrc or .zshrc: NPM_PACKAGES="${HOME}/.npm-packages" export PATH="$PATH:$NPM_PACKAGES/bin" # Preserve MANPATH if you already defined it somewhere in your config. # Otherwise, fall back to `manpath` so we can inherit from `/etc/manpath`. export MANPATH="${MANPATH-$(manpath)}:$NPM_PACKAGES/share/man" 2. Install/Use node using nvm or asdf Node’s official documentation recommends installing node as an unprivileged user using a node version manager. ...
Webhook to auto-deploy on git push to Github
What is a webhook? A webhook is an endpoint on your server which allows you to execute a particular task. Webhooks are usually triggered by some event. A good use-case for a webhook is running tests on a dedicated test server or deploying your latest master branch to staging/production. Github / Gitlab / Bitbucket allow you to specify a webhook URL in your repository settings. Github triggers the webhook which sends the event data on every push. Webhook server Webhook is a very useful golang project which runs any script you specify when a particular endpoint is hit. Download and extract the binary for your operating system from the releases page. For Linux, it is here. The program takes as config a hooks.json file: [ { "id": "hello-world", "execute-command": "/home/user/scripts/hello.sh", "command-working-directory": "/home/user/webhook" } ] Replace user with the username of your linux user. The hello.sh script. #!/bin/bash echo 'Hello!' Make the script executable by running chmod +x hello.sh Start webhook server as webhook -hooks hooks.json -hotreload -logfile webhooks.log. The server will run on port 9000 by default. You can check if everything is working by running curl http://localhost:9000/hooks/hello-world. This will print “Hello!” in the log file. ...
Bash function to add TILs
til snippet Here’s a snippet I use in my .bashrc file to quickly write down and review TILs (Today I learned): TIL_FILE="$HOME/my-notes-repo/til.md" til () { # checks if the function has been called without any argument if [[ -z $1 ]]; then # opens the file in my editor, setting the cursor to the last line # useful to review latest entries or to write a longer entry vim + "$TIL_FILE"; else # adds a line with today's date, a TAB and all arguments supplied ("$@") echo -e "- $( date '+%F' ):\t$@" >> "$TIL_FILE"; fi } How to use: til to open the file. I use this to review what I learned today or if I need to write a longer, multiline entry til CONTENT to append a line to the file e.g til grep --line-buffered to immediately print especially when tailing files will add this: - 2020-05-23: grep --line-buffered to immediately print especially when tailing files Explanation on the function In case you missed the comments in the function, here’s an explanation of what the various lines do: ...
Setting display brightness on Linux from the command line
Setting display brightness using xrandr I auto-adjust the brightness on my display using a cron which runs at 7 pm everyday. xrandr --output eDP-1 --brightness 0.9 This sets the brightness to 90% of maximum brightness. Working with Linux Display environments in a cron The above command works when run from my terminal. But when run on a cron, it does not produce any effect. We need to explicitly mention the “display number” as an environment variable DISPLAY. 8 19 * * * DISPLAY=:0 xrandr --verbose --output eDP-1 --brightness 0.9 How to get the display number of your monitor? Running xrandr will give you a lot of output like Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 16384 x 16384 eDP-1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) In my case, the display number is :0 Adjusting backlight brightness vs perceived brightness If xrandr is unable to find backlight, it only changes “perceived” brightness i.e it does software color correction. If we want to save battery, we will need to reduce the backlight brightness. ...
Easy VPN using Wireguard
Why Wireguard and How does it work? Simple (one config file on server and client and one command to run) Small codebase (5000 LOC) unlike OpenVPN and IPSEC Scheduled to be merged into Linux kernel soon Wireguard works by creating a tunnel to the server using a separate network interface on your machine. You do not need to worry about Proxy settings and all your applications will work without issue. Installation and Key Generation Do this on both server and client machines #Installation: For both machines sudo apt install wireguard wireguard-tools openresolv # openresolv is in case you are using systemd-resolved which is default for DNS resolution on Ubuntu # Generate private and public key pair : For both machines umask 077 wg genkey | tee privatekey | wg pubkey > publickey Configure Server Create file called /etc/wireguard/wg0.conf [Interface] PrivateKey = <Private Key> ListenPort = <UDP Port to listen on, by default it is 51820> Address = 192.168.2.1/24, fd86:ea04:1115::1/64 ListenPort = 51820 PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE SaveConfig = true [Peer] PublicKey = <Client Public Key> AllowedIPs = 192.168.2.2/32 Note that you have to paste the contents of the private key in the conf file, not the path. The PostUp sets up forwarding rules when the wiregaurd interface is started. PostDown deletes the rules when the interface is shutdown. Packet forwarding is essential if you want to use your server as a VPN to the general internet. Enable it on your server by adding the following to /etc/sysctl.conf and run sudo sysctl -p to reload the configuration changes. ...
Git Tagging Tutorial
I read a post on dev.to which shows how to create git tags using GUI-based git clients. I think that tags are useful to know even when using the git cli. What are tags Tags are specific points in your code history which are useful to re-visit later e.g you just released a new version of your app. You can tag the commit as v1.0 using git tag v1.0. Anytime you want to reproduce bugs encountered on that version, simply do git checkout v1.0 and investigate. How to use git tag better Checkout code to the tag The tag is linked to the specific commit and not to a branch. When you checkout the tag, git tells you that you are in “detached HEAD” state. Do not worry, all it means is that you need to create a new branch if you want to retain any changes you make after checking out the tag. Create a new branch exactly at the commit of the tag using git checkout -b BRANCH_NAME TAG_NAME ...