A Collection of Random Things

Things I come up sometime

我感觉我这几年跟我前任和他的飞猴们的对线的故事都够我写小说了。既然最近想说练练写故事,就发出来玩玩把。

我跟有毒前任分手一年了,结果这个朋友最近somehow在小软件上划到了我前任。然后就有了下面的对话,内容打了薄码:

对话1

跟他出去吃饭,莫名奇妙突然就开始问到我前任。

“你为什么在小红书上吐槽你ex?”

我感到无比懵比,吐槽前任也不是什么大不了的事情,不是还有个tag是我的前任是个奇葩么?这夹枪带棒劈头盖脑是几个意思?

“就是吐槽,纯树洞,怎么了?”

“##(我ex的名字)问我你是不是在他背后散布什么他的不好消息。我觉得这种事情发出来挺不好的, 好在你没有指名道姓,所以我就跟他说没什么影响。”

“怎么了?怕他人设受影响么?“

“我就好奇你为什么会吐槽他, 我最近跟你ex接触了一下,觉得他人很好。而且我有个朋友###也认识你ex,说他人特别好。”

:ㄟ( ▔, ▔ )ㄏ

对话2:

后来和其他几个朋友聚餐,结果他又突然提起我前任。

“我最近一直在和你ex聊天,我觉得他对我挺有兴趣的,我也觉得他人特别sweet,上次说他亲自给我做了饭带过来,还请我到他家去他做饭给我吃。所以你觉得他不好的原因是什么?”

我当时内心真是万马奔腾。这话术,这小手腕,这不就是当年对那个无知的我用的么:特地去买了我最喜欢吃的东西都带到我楼下了,但是发现我没回他消息就只好先走了。但是,我当时根本就没告诉他我住哪( ̄_, ̄ ),>但是毕竟有别人在场,我不太喜欢大谈自己私事,就敷衍他说:“我觉得可能我跟他不太合适吧,你如果觉得他很好你可以处处试试。”然后岔开话题。

但是他又把话题扭了回来。

“他说你们分手的原因是那天你过生日,但是他亲戚那天结婚,他心里特别想你也一起去,但是你只考虑自己的生日,完全没想过他的感受。”

前任在我生日那天跟我分手,小丑居然是我?我觉得就算我再十恶不赦,也不用挑过生日分手吧。我不想陷入自证陷阱,但是也不想就这么成了小人,就说:“事实上我去了啊,只是提前离开了,他没跟你说么?”

对面若有所思的样子。

“whatever,而且他说他一直有在反思,说你俩都有错。但是你一直不喜欢承认自己的错误。”

这种pua话术我真的已经免疫了,再聊就会涉及很多私事,有外人在场,真不想聊这些,就跟他说:“是么。我还是那句话,One man’s poison, another man’s medicine。”

对话3:

因为白天觉得他眼神涣散,跟他平时的气场差了很多,我就发了个消息,想问他要不要聊聊,更主要是真心想提醒他不要轻信我那个前任。

“你听说过飞猴么?”我问他。

“没有,你说你前任是飞猴么?”

“不是。咱们也算是蛮久的朋友了,我就是提醒下你不要被他当枪使。你乐意和他干什么是你们的事。你跟他聊什么也是你俩的事,我管不着也不想管。我就想说,咱们出门在外都不容易,别被某些别有用心的人趁虚而>入。”

“你这不还是管了么?”

“我只是想提个醒,哪里管了?”

“你为什么又和我argu?你总是这样。”

“总?又?那打电话说吧。”

几分钟后给他打了电话。

“你为什么会觉得我在和你argu?”我尽量很平静的问他。

“因为发文字本来就是这样,你又加了个问号,我会觉得你在和我argu。”

“那打电话说正好。”

“我觉得你前任完全不是你跟我形容的那样。”

“我跟他在一起两年多,你跟他刚认识,我觉得我对他的了解可能更多一些。”

“但是可能就是你跟他不合适,但是我就跟他合适呢?”

“好吧。你要是觉得你能跟他相处得更好,那你就试试吧,我只是给你提个醒, 没别的意思。”

电话对面明显暴怒。

“omg。你这人真的有问题,为什么一定要“更好”呢,比来比去有意思么?我跟你没什么可比的,就是合适不合适。”

“那可能是我用词不当,我并没有比较的意思。我还是那个one man’s poision的观点。我觉得觉得你也是这个意思。但是我觉得我们俩也是认识蛮久的朋友了,我只是作为朋友不得不说。”

“我找你要unsolicited advice了么?”

感觉对面声音在颤抖。

我赶紧想缓和一下气氛:“那我们换位思考一下,假设我们是好朋友,或者说这事情发生在你闺蜜身上,你看到她前面有个大坑,你是闭嘴不说话,还是提醒你闺蜜不要踩坑?”

“你这个假设的前提是我们是好朋友,但是我不觉得我们是很好的朋友吧?”

我很震惊我当时居然一点情感波动都没有,大概是把他定义为飞猴后,心里已经把他和我前任归为一类人了。怎么回应这些话,跟我前任不知道练了多少次,久了也会麻木把,我于是平静的跟他说:“好吧,那可能是我单>方面觉得你是我朋友吧。尽管如此,该说的也说了。不过你为什么不觉得我们是朋友?”

“我觉得你这人心防特别重,我一直不知道你在想什么。比如,上次我妈在的那次你来我家吃饭,你表现得特别拘谨,有必要么?”

“我觉得我本来就是i人社恐面对一堆不认识的人,还有长辈肯定会拘谨啊?那你说应该怎么表现?”

“你就不能表现得大方一点,外向一点?”

“我本来就不是什么外向的人,也装不出来,再说这跟朋友不朋友有什么关系?”

“那我就觉得我跟你这种人合不来吧。而且我觉得你真的应该先找找你自己身上的问题。”

“我什么问题你说来听听?”

“你什么问题你自己清楚。”

这些话术我我在前任那里听了太多,基本已经免疫了把。既然你不把我当朋友,那我也就不当你是朋友呗。于是我就直接跟他说:“好吧。既然咱们也不是朋友,那我就爹味十足的告诉你怎么做人。我告诉过你一些我和前>任一些比较私人的事情,是因为当时足够信任你;我不喜欢跟一些不那么熟的人讨论我的私事,你今天把这些拿来大庭广众就是你做事不地道。反正我很不爽。”

能听出对方很不屑。

“这有什么了,再说###【吃饭时在场的其他人】都我的好朋友,他们不会到处乱讲的。我只是把问题摆到台面上,大家开诚布公。”
“你怎么知道他们不会到处乱讲?”

感觉对方更加不屑。

“你看,这就是你的问题了,心防太重,这些事情拿出来说有什么大不了的?”

“那我觉得我们也没什么好说了,祝你幸福。”说完我就直接挂了电话。

What is hash? According to vocabulary.com, hash is “chopped meat mixed with potatoes and browned”. In computer world, hashing bears similar meaning, objects come in with different format disparate content and it’s the job of hashing to chop them, mix with necessary other ingredients then finally present them in a uniform way, a.k.a, fixed length value.

One prominent usage of hashing is hashtable. A hash table is as simple as: given an arbitrary key can be uniquely mapped to a value. Fitting a small hashtable in memory on a single machine is trivial, but on a larger scale, when the size of the hashtable stretches beyond the limitation of a physical machine, we need to resort to something called consistent hashing.

Consistent hashing is a way of breaking a giant hashtable into manageable smaller hashatables which fit into single physical machine. Imagine it as a round canal with water moving in one direction. Boats (or hash keys) are tossed randomly into the canal and move along with the current and. Ultimately, the boats need to be loaded with goodies (or hash values), before they can exit the canal. This can only be done when boats arrive at the next closest station (or physical machines). In this sense, consistent hashing solves the following problems:

  1. Toss a boat and you will get a boatload of goodies
  2. Stations can be added and removed freely, if too many boats are in some parts of the canal, it might be wise to add more stations; whereas stations can be suspended if boat traffic is light. The following code snippets demonstrate how these two scenarios work:

The above-mentioned functions can be abstracted into the following class interface

1
2
3
4
5
6
7
8
9
10
11
12
class ConsistentHashing:
def add_node(self, node_id):
pass

def remove_node(self, node_id):
pass

def get(self, key):
pass

def add(self, key, value):
pass

To lay the ground for this data structure, we need to first construct a Ring class that add or override the following functions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Ring(dict):
def __getitem__(self, key):
pass

def __setitem__(self, key, value):
"""
For constistent hashing ring, we probably don't want to allow adding duplidate nodes into the ring
We want to find the next availabe node and insert the key value into there
"""
pass

def __delitem__(self, key):
pass

def override_node(self, key, value):
pass

def get_next_node(self, key):
"""
The next node following the given key will strictly be the "next node" regardless if the key exists on the ring or not
"""
pass

The full code will look like this, I put comments inline:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
from collections import OrderedDict
from bisect import bisect_right, insort_left


class Ring(dict):
def __init__(self, **kwargs):
super(Ring, self).__init__(**kwargs)
self.__sorted_keys = [key for key, _ in self.items()]
self.__sorted_keys.sort()

def __getitem__(self, key):
if key in self:
return super(Ring, self).__getitem__(key)

index = bisect_right(self.__sorted_keys, key)
if index >= len(self.__sorted_keys):
raise "The given key: {key} does not exist".format(key=key)

return self[self.__sorted_keys[index]]

def __setitem__(self, key, value):
"""
For constistent hashing ring, we probably don't want to allow adding duplidate nodes into the ring
We want to find the next availabe node and insert the key value into there
"""
if key in self:
raise Exception("Key: " + str(key) + " already exists")
super(Ring, self).__setitem__(key, value)
insort_left(self.__sorted_keys, key)

def __repr__(self):
return "Ring: {" + ", ".join(str(key) + " : " + str(self[key]) for key in self.__sorted_keys) + "}"

def __str__(self):
return self.__repr__()

def __delitem__(self, key):
super(Ring, self).__delitem__(key)

if key in self.__sorted_keys:
self.__sorted_keys.remove(key)

def override_node(self, key, value):
super(Ring, self).__setitem__(key, value)
if key not in self:
insort_left(self.__sorted_keys, key)

def get_next_node(self, key):
"""
The next node following the given key will strictly be the "next node" regardless if the key exists on the ring or not
"""
index = bisect_right(self.__sorted_keys, key + 1 if key in self else key)
if index >= len(self.__sorted_keys):
raise "The given key: {key} does not exist".format(key=key)

return self.__sorted_keys[index]


class ConsistentHashing:
def __init__(self, num_nodes, initial_space):
"""
To demonstrate, I used even spacing to initialize the ring. A node with key equals infinite number is added to handle boundary condition.
The node is prepresented as a dictionary, so we have a dictionary (ring) of dictionaries (node)
"""
self.__num_nodes = num_nodes
self.__nodes = Ring()

for i in range(self.__num_nodes):
self.__nodes[(i + 1) * initial_space] = {}

self.__nodes[float("inf")] = {}

def add_node(self, node_id):
"""
Adding node involves the following two actions:
1. Create a new node on the ring
2. Move the appropriate key value pairs from the downstream node to this new node
"""
self.__nodes[node_id] = {}
next_node = self.__nodes.get_next_node(node_id)
org_node_content = {}
for key, value in self.__nodes[next_node].items():
if key <= node_id:
self.__nodes[node_id][key] = value
else:
org_node_content[key] = value

self.__nodes.override_node(next_node, org_node_content)

def __repr__(self):
return self.__nodes.__repr__()

def remove_node(self, node_id):
"""
Removing node involves the follow tow actions:
1. Move all the key value pairs to the downstream node
2. Delete the current node
"""
next_node = self.__nodes.get_next_node(node_id)
for key, value in self.__nodes[node_id].items():
self.__nodes[next_node][key] = value

del self.__nodes[node_id]

def get(self, key):
return self.__nodes[key][key]

def add(self, key, value):
self.__nodes[key][key] = value


if __name__ == '__main__':
h = ConsistentHashing(num_nodes=4, initial_space=5)
h.add(1, "apple")
h.add(5, "orange")
h.add(7, "pear")
h.add(15, "watermelon")
h.add(19, "chia")
h.add_node(3)
print(h)
print(h.get(5))
h.remove_node(3)
h.remove_node(10)
h.remove_node(20)
print(h)
print(h.get(1))

How does this work?

  1. We start with a ring containing 4 nodes (an extra inf node to handle boundary condition)
  1. Key value pairs are added accordingly, for example, key 1 is tosses onto the ring and it follows the downsteam to node 5
  1. The result of the ring can be seen below
  1. A new node 3 enters the ring, so the key 1 and its value gets moved to node 3
  1. Node 3, 10, 20 leave the ring, the key value pairs are shuffled accordingly.

To demonstrate, we start from the interface, a consistent hashing data structure should be able to do the following

Why we want to use sp_executesql

One use case for this stored procedure is when we need to do parameterized linked query using OPENQUERY. I could have constructed a string with the parameter decorated by some special characters such as {{Parameter}} (This resembles the handlebar a lot, or AngularJS) and use EXEC to execute the query. However, a fundamental flaw with that approach is that I will not be able to return a value since the query cannot be parameterized. With the help of sp_executesql, we are able to provide input and output parameters

Read more »

Having played with Nodejs for a while, I decided to try some other web framwwork for a change, having used Tomcat a little bit, I decide to try a simple java based restful service with Jersey + Tomcat. Most of the online tutorials are based on eclipse or based on maven. Here I am using Intellij with gradle. I used this article as reference.

Read more »

我在写这个开头的时候,脑中跳出的头一句是:“2015是变革的一年,是发展的一年,是丰收的一年”。可以是觉得有点写思想汇报即视感,于是作罢。
想要写点什么新奇的东西,可以又觉得任凭我怎么总结2015都会有所疏漏,因而作此文不为总结,只为留下些东西,权作日后的参考。

Read more »

Consider the following scenario, we are creating a set of dropdowns each displays a series folders in a file system. User will click a dropdown to view all the folders (or files), then make a selection. After selection is made, all the dropdowns following the one user interacted with will change to show the subfolders (or files, if there are any) in the folder the user has selected.

Read more »

John Resig’s book ‘Secretes of the JavaScript Ninja’ is really a fun and inspiring masterpiece to read. I believe it is one of the JavaScript book you should keep on your desk for study and reference. I am going to write something to summarize some important and interesting usages of .call(), .apply() and .bind() for my reference.

Read more »

I have been working with ILNumerics.NET for quite a while. It is a fine piece of mathmatical library which provides better performance than most of the other .NET numeric libraries. Used properly, it’s performance can also surpass that of MATLAB.

Read more »
0%