Skip to content
Advertisements

Tagdevelopment

Ruby Class Members: Getter & Setter

The simplest example of read_attr, write_attr in a class.

class Person  
  attr_reader :name, :age   
  attr_writer :name, :age   # creates the setter methods       
    
  def initialize(name)  
    [@name](http://twitter.com/name) = name  
  end  
endmike = Person.new('Mike')   
mike.age = 20               # calling setter method  
mike.age                    # calling getter method, returns 20

Reference

The example is verbatim from an easy to follow tutorial on Ruby class: https://medium.com/@rondwalker22/how-getter-setter-methods-work-in-ruby-c5f5da07f99

Ubiquitous Client for Redis Server: Netcat

Forget about redis-cli.

Just use nc

bash-5.0# nc -v  10.x.x.x 6379
10.x.x.x (10.x.x.x:6379) open
select 14
+OK

What is ncat?

NAME
     nc -- arbitrary TCP and UDP connections and listens

SYNOPSIS
     nc [-46AcDCdhklnrtUuvz] [-b boundif] [-i interval] [-p source_port] [-s source_ip_address] [-w timeout] [-X proxy_protocol] [-x proxy_address[:port]] [--apple-delegate-pid pid] [--apple-delegate-uuid uuid] [--apple-ext-bk-idle]
        [--apple-nowakefromsleep] [--apple-ecn mode] [hostname] [port[s]]

DESCRIPTION
     The nc (or netcat) utility is used for just about anything under the sun involving TCP or UDP.  It can open TCP connections, send UDP packets, listen on arbitrary TCP and UDP ports, do port scanning, and deal with both IPv4 and IPv6.
     Unlike telnet(1), nc scripts nicely, and separates error messages onto standard error instead of sending them to standard output, as telnet(1) does with some.

Reference

SIngle Thread LRUCache in C++

#include <iostream>
#include <list>
#include <unordered_map>

using namespace std;

size_t capacity;

class LRUCache
{
public:
    bool Lookup(int key, int *price)
    {
        auto it = hash_table.find(key);
        if (it == hash_table.end())
        {
            return false;
        }

        *price = it->second.second;

        // update the key in the queue
        MoveToFront(key, it);
        return true;
    }

    void Insert(int key, int price)
    {
        auto it = hash_table.find(key);
        if (it != hash_table.end())
        {
            MoveToFront(key, it);
            return;
        }

        if (hash_table.size() == capacity)
            CleanTable();

        lru_queue.emplace_front(key);
        hash_table[key] = {lru_queue.begin(), price};
    }

    bool Erase(int key)
    {
        auto it = hash_table.find(key);
        if (it != hash_table.end())
        {
            lru_queue.erase(it->second.first);
            hash_table.erase(it);
            return true;
        }
        return false;
    }

    void PrintQueue()
    {
        for (auto it : lru_queue)
        {
            cout << it << " ";
        }
        cout << endl;
    }

private:
    typedef unordered_map<int, pair<list<int>::iterator, int>> Table;
    Table hash_table;

    void MoveToFront(int key, const Table::iterator &it)
    {
        // delete the node.
        lru_queue.erase(it->second.first);

        // create a new node at the front.
        lru_queue.emplace_front(key);
        it->second.first = lru_queue.begin();
    }

    void CleanTable()
    {
        hash_table.erase(lru_queue.back());
        lru_queue.pop_back();
    }

    list<int> lru_queue;
};

int main()
{
    capacity = 3;
    LRUCache cache;

    cache.Insert(1, 100);
    cache.Insert(2, 200);
    cache.Insert(3, 300);

    cache.PrintQueue();

    cache.Insert(4, 400);
    cache.PrintQueue();
}

Output

$ g++ -std=c++11 ./LRUCache.cpp
$ ./a.out
  3 2 1 

  4 3 2 

Benefits & Caveats

  • O(1) operations
  • Single thread operation
  • Each CleanTable results in free and malloc in the lru_queue

Notes on Go Structure Tags

Go has a feature to create a user-defined type with struct. Go also allows the program to specify meta-information with structure field.
This meta-information is called Tags. A tag usually helps in packaging/unpacking a user-defined type structure.

  package main

  import (
      "encoding/json"
      "fmt"
  )

  type Test struct {
      // json tags indicate the key name to use in json data
      Name    string `json:"myname"`
      Country string `json:"region"`
  }

  func main() {
      // The order of json need not match the order of structure fields.
      p := map[string]string{"region": "earth", "myname": "hello"}

      marshalled, err := json.Marshal(p)
      fmt.Println(marshalled, err)

      // get the var back from marshalled data
      var m Test
      json.Unmarshal(marshalled, &m)
      fmt.Printf("name=%v\n", m.Name)
      fmt.Printf("name=%v\n", m.Country)
  }

Why should I use json tags

  • The benefit of json tags is the flexibility to marshal with either a JSON or a struct.
  • JSON input for marshaling is convenient and flexible with elements ordering.

Reference

Adding Query Params to a URL in Ruby with HTTP

The clearest example was in a StackOverflow post

require 'uri'

def add_param(url, param_name, param_value)
 uri = URI(url)
 params = URI.decode_www_form(uri.query || "") << [param_name, param_value]
 uri.query = URI.encode_www_form(params)
 uri.to_s
end

You can pass a map of params key & values and get expected URL.

Another example

 # prepare params.
 params = { 'id' => '12' }

 path = 'http://localhost/'
 uri = URI(path)

 uri.query = URI.encode_www_form(params)

Output

http://localhost?id=12

Reference

How to Change View of Coding Block in WordPress?

Problem

Many times a good WordPress theme does not render code properly. There are problems like too big font making it harder to read the text. I use StackEdit to prepare posts and publish to my blog.

Solution

There is a way to solve this problem with custom CSS.

Description

The posting source is in Markdown. StackEdit translates MarkDown to HTML and posts to the destination. There is not much I could do with the Markdown. However, the theme on the WordPress blog allows me to set a CSS for particular content.
The code blocks are translated to pre blocks in the HTML. So adding a custom rendering for pre block should fix the problem.
I found a CSS snippet from https://wp-mix.com/css-style-pre-tags/.

pre {
	box-sizing: border-box;
	width: 100%;
	padding: 0;
	margin: 0;
	overflow: auto;
	overflow-y: hidden;
	font-size: 12px;
	line-height: 20px;
	background: #efefef;
	border: 1px solid #777;
	background: url('lines.png') repeat 0 0;
	padding: 10px;
	color: #333;
}

Another good reference is https://perishablepress.com/perfect-pre-tags/

This made the code look much much better.

Update

One More Reason to Avoid Ruby Language

Ruby is type unsafe language but it goes a step further and avoids checking dynamically too.

Consider this code

x = :abc
if x == 'abc'
  puts "Symbol and String are two different classes"
else
  puts x.class, 'abc'.class
end

# puts can print a symbol and string alike.
puts x

My Complaints

  • I’m new to Ruby. How could Ruby let a Symbol and String compare, in spite of being aware of their types? Like Python, it can throw an error.
  • How can puts print a Symbol as good as a String

References

C++: Max Product in a Matrix witout Backtrack

Problem

Given a matrix, find the path from top left to bottom right with the greatest product by moving only down and right.

The code is in C++.
The only moves allowed are down and right. The solution works for positive numbers.

Reference

Written with StackEdit.

A Resilient Web API Client in Ruby

Ruby HTTP client is not sophisticated enough to handle errors gracefully. I came across a well-designed client for a web service at [AppSignal].
(https://blog.appsignal.com/2018/05/16/ensure-retry-and-reraise-exceptions-in-ruby.html)

The code for the client is as following:

The code has the following logic:

  1. Try to establish a connection with the server.
  2. The request has a timeout and connection refused exceptions.
  3. If retries fail, code raise the last seen exception.
  4. Each retry has increased timeout.

Written with StackEdit.

Golang: Switch-case does not fall through!

Unlike C/C++ switch-case statements, Golang switch case does not fall through.

package main
import (
	"fmt"
)

func main() {
	fmt.Print("Go runs on ")
	os := "darwin"
	switch os {
	case "darwin":
	case "linux":
		fmt.Println("Linux.")
	default:
		// freebsd, openbsd,
		// plan9, windows...
		fmt.Printf("%s.\n", os)
	}
}

The above code does not print anything!

package main
import (
	"fmt"
)

func main() {
	fmt.Print("Go runs on ")
	os := "darwin"
	switch os {
	case "darwin":
	fallthrough
	case "linux":
		fmt.Println("Linux.")
	default:
		// freebsd, openbsd,
		// plan9, windows...
		fmt.Printf("%s.\n", os)
	}
}

You have to add fallthrough statement to make it work. The above code prints Linux.

Pre-Deployment Checklist for Developers

  1. Handled all error conditions?
    Have you checked each error and handled or propagated upstream?

  2. Returned appropriate error code
    Please return proper error code & detailed error message to callers.

    msg := fmt.Printf("[fname] failed in Redis Set err=%s ret=%d", err, ret)
    ret errRedis
    
  3. Added logs for each failure
    It will help you narrow down the trouble code.

  4. Successful build with lint
    lint keeps your code clean.

  5. Formatting fixes (gofmt)
    Always follow the coding standard of the language, especially symbol names.

  6. Code reviews by at least two people.

  7. Unit Testing (docker compose)
    UT is easy and catches stupid bugs. There are many ways to test the code. The easiest is just the functions you’ve added. Stub any call you don’t or can’t test.

  8. Scale testing (for finding a resource such as sockets, memory leaks)
    UT is ineffective catching serial and slow bugs. These are the most troublesome problems that can be caught using heavy load & volume testing

  9. Staging deployment

  10. Finally, live on production 🙂

How to Select a Random Key from a Hash Map in Constant Time?

Premise

A hashmap has a time complexity of O(1) for all operations.

Problem

You have to find a constant time method to uniformly random selection of a key in a Hash map.

Assumptions

  1. The map can grow to memory size.
  2. You can use any readymade hash map.

Solution

I’m discussing the pseudo code for a Python solution. All operations work in constant time except remove().

randMap = {}

def insert(k, v):
    randMap[k] = v    

The random must pick a random key. But how? We can store all the keys in a list and then run random() on the list indexes.

randMap = {}
indexMap = {}
keyList = []
last = 0
def insert(k, v):
    randMap[k] = v
    keyList.append(k)
    last += 1
    
    # Maintain index of each key
    indexMap[k] = len(keyList)    
def getRandom():
    start = 0
    end = len(keyList) - 1
    randomIndex = random(start, end)
    key = keyList[randomIndex]
    
    return key

How do you delete a key?

This is the crux of the problem. Deletion of a key would need us to change the index array too. That means we need to shift all elements of the array and complexity would shoot to O(n).

def remove(k):
    # Remove from the hash map
    randMap.pop(k, None)
    
    # Remove from key list
    index = indexMap[k]
    
    # This is O(n) operation
    keyList.remove(index)

    # Pop the index too
    indexMap.pop(k) 

How to improve deletion?

  1. Delete the entry and mark the entry invalid. The probability distribution does not change, however with more and more deletions, you have a sparse array. Thus you would need multiple getRandom() to get a valid key.
  2. Move the last element to the deleted element. Adjust the index of the last element.
def remove(k):
    # Remove from the hash map
    randMap.pop(k, None)

    index = indexMap[k]
    indexMap[last] = index
    
    # This is O(1) operation
    keyList[index] = keyLast[last]

    # Pop the index too
    indexMap.pop(k)
    last -= 1 

This is a constant time solution.

%d bloggers like this: