dotnet 世界猜測 隨機數的小測試

這是一個半技術向的博客,主題來源于我讀過的某本書的片段,這是一個稍稍有些前置知識的故事,主題的大概內容就是假定世界存在某個規則序列,通過一代代的探索,可以獲取到此序列的內容。本文將模擬此情形,寫一個隨機數的小測試應用,來不嚴謹的證明,或者準確來說是用代碼講述這個故事

天有五賊,見之者昌。 傳說,在一個由某逗寫的代碼世界里面,世界里藏著一段取值范圍為 0 到 100 且長度為 10 的序列。某逗將此序列稱為世界序列。在此世界里面,還生活著一群名為 Element 的小人兒。這些 Element 小人兒,都在探索和追求著世界序列。因為呀,每當此世界經過一代的時候,嗯,約等于某個大循環執行一遍的時候,將會根據此世界序列的內容,再加上某逗規定的算法,決定哪些 Element 小人兒需要被淘汰掉。已知的是,如果 Element 小人兒越了解準確世界序列,那 Element 小人兒就越能生存下來

此世界每經過一代,將會淘汰一批 Element 小人兒。而存活下來的 Element 小人兒將會迎來新的一輪生娃過程。可以由存活下來的 Element 小人兒創建出更多的下一代的 Element 小人兒

在經過此世界的很多代之后,咱來看看存活下來的 Element 小人兒是否都掌握了正確的世界序列

接下來就是寫代碼的內容了,命題確定了,其實通過簡單的大學數學的知識,是能夠計算出結果的,只不過咱是計算機系的,肯定要寫點代碼啦

按照本文的題注,天有五賊,見之者昌,先用代碼寫天有五賊。我的文學修養還不夠,不能達意的解釋天有五賊,見之者昌這句話。只能用代碼的方式,以一個片面的方式來解釋。在某逗寫的代碼世界里面,此世界的世界序列就是對應著天有五賊的意思。這片天地有五賊,五賊大概就是金木水火土五行的意思,也等于說世界的規則或者說世界的本源。本文的世界序列,就大概屬于某逗寫的代碼世界里面的本源。而見之者昌可以認為是,如果有人可以知曉五賊,約等于說如果有人可以知道世界的規則或者說世界的本源,那他將會昌盛。對應某逗寫的代碼世界里面的 Element 小人兒,如果 Element 小人兒能夠知曉世界序列,那他更能在此代碼世界的一代代循環里面存活,而且 Element 小人兒也就能生產更多的下一代的 Element 小人兒,不斷昌盛

某逗寫的代碼世界里的世界序列,序列里面的每個項,都可以用一個 Key 的只讀結構體來表示。之所以不直接使用 int 等來表示,那是為了給一個單位,這屬于程序員的修養。如以下代碼定義了 Key 這個只讀結構體,本文代碼基于 dotnet 7 版本編寫,本文代碼都在 GitHub 上開源

readonly record struct Key(int N)
{public const int MaxKeyValue = 100;
}

世界序列也就是一個?List<Key>?類型。當然,有了代碼世界,為了代碼世界能夠好好工作,還需要一個世界管理者,也就是以下代碼定義的 Manager 類型,在 Manager 里面就存放了世界序列,代碼如下

class Manager
{public List<Key> KeyList { get; }... // 忽略其他代碼
}

生活在代碼世界里面的是一群 Element 小人兒,使用的是 Element 類型,每個 Element 小人兒都有自己的一段序列。這就是 Element 小人兒最重要的,也是不斷探索的內容

class Element
{public List<Key> KeyList { get; } = new List<Key>();... // 忽略其他代碼
}

在代碼世界剛開始的時候,也就是 Manager 被創建出來的時候,將會立刻初始化世界序列

public Manager(){KeyList = new List<Key>();for (int i = 0; i < 10; i++){var key = Random.Shared.Next(Key.MaxKeyValue);KeyList.Add(new Key(key));}}

世界開始的時候,將會進入 Manager 的 Start 方法,在初始化世界時,將會創建出首批的 Element 小人兒,如以下代碼,由于怕電腦被玩壞,這里約束了 Element 小人兒的數量大概只有 10000 個

class Manager
{public void Start(){for (int i = 0; i < 10000; i++){var element = CreateElement();ElementList.Add(element);}}public List<Element> ElementList { get; } = new List<Element>();... // 忽略其他代碼
}

以上的 CreateElement 方法是一個用來輔助創建 Element 小人兒對象的方法,在實現他之前,還請先看看 Element 類型的構造函數吧

在 Element 類型里面,不僅包含了 KeyList 屬性,還包括了兩個輔助代碼運行的屬性,分別是 Random 隨機數屬性和 FinishBuildKey 屬性,還請讓我賣個關子,在本文后續部分再來揭曉 FinishBuildKey 屬性的作用。在 Element 類型的構造函數里面,將要求傳入 Random 屬性,以讓 Element 在每一代里面,擁有猜測世界序列的能力,且多個 Element 之間有奇妙的關系

class Element
{public Element(Random random){Random = random;}public Random Random { get; }private bool FinishBuildKey { get; set; }public List<Key> KeyList { get; } = new List<Key>();... // 忽略其他代碼
}

在了解到 Element 的構造函數之后,相信大家也能猜到 CreateElement 方法的實現了

private Element CreateElement(){Element element = new Element(new Random(Random.Shared.Next()));return element;}

在完成了代碼世界的首批 Element 小人兒創建之后,就要進入激烈的世界迭代了。先創建一個大循環,大概是 10000 次。表示這個世界將會開始迭代 10000 次

for (int i = 0; i < 10000; i++){... // 忽略其他代碼}

在每一代的開始時,都會讓每個 Element 小人兒進行一輪思考,讓 Element 決定是否在自己的 KeyList 里面,加上新的 Key 值。當然,每個 Element 小人兒的思考方式,現在就是通過 Random 隨機數生成的哈

for (int i = 0; i < 10000; i++){foreach (var element in ElementList){element.BuildKey();}... // 忽略其他代碼}

以上的 BuildKey 函數就是放在 Element 里的函數,用于讓 Element 小人兒思考新的 Key 值是什么,大概的實現如下

class Element
{public bool BuildKey(){var key = Random.Next(Key.MaxKeyValue);KeyList.Add(new Key(key));return true;}... // 忽略其他代碼
}

當然了,有些 Element 小人兒決定放棄思考,也就是 Element 可以不再生成新的 Key 值。這也就是上文賣關子的 FinishBuildKey 屬性的作用,此屬性用來判斷是否此 Element 已不再生成新的 Key 值了,約等于此 Element 認為自己已猜出了世界序列

class Element
{public bool BuildKey(){if (KeyList.Count > 0 && (FinishBuildKey || Random.Shared.Next(10) == 1)){FinishBuildKey = true;return false;}var key = Random.Next(Key.MaxKeyValue);KeyList.Add(new Key(key));return true;}... // 忽略其他代碼
}

等待各個 Element 思考完成之后,此代碼世界的考驗就要開始了。在此世界的天道規則是從當前的世界序列里面通過當前世界的代數,也就是世界大循環的 i 變量的值,決定出世界序列中的一個 Key 值。對于每個 Element 來說,也要根據當前世界的代數返回一個 Key 值。一旦 Element 的返回的 Key 和此世界的 Key 值不相同,那么此 Element 將會被淘汰

說起來簡單,先來看看代碼如何實現

先實現從當前的世界序列里面通過當前世界的代數,也就是世界大循環的 i 變量的值,決定出世界序列中的一個 Key 值

class Manager
{public void Start(){... // 忽略其他代碼for (int i = 0; i < 10000; i++){... // 忽略其他代碼var key = GetKey(i);... // 忽略其他代碼}}public Key GetKey(int n){var index = n % KeyList.Count;return KeyList[index];}... // 忽略其他代碼
}

每個 Element 也實現 GetKey 方法,也是通過傳入的序號返回一個 Key 值

class Element
{public Key GetKey(int n){var index = n % KeyList.Count;return KeyList[index];}... // 忽略其他代碼
}

判斷 Element 返回的 Key 是否和世界的相同,如果不相同,將會淘汰。代碼只需要一句話就可以完成實現,那就是返回 Key 不相同的,從 Manager 的 ElementList 列表里面移除

class Manager
{public void Start(){... // 忽略其他代碼for (int i = 0; i < 10000; i++){... // 忽略其他代碼var key = GetKey(i);ElementList.RemoveAll(element => element.GetKey(i).N != key.N);... // 忽略其他代碼}}... // 忽略其他代碼
}

對于從 ElementList 被移除的 Element 來說,等待這些 Element 就是凌駕于此世界之上的 dotnet 的 GC 回收機制將其當初垃圾清理掉

經過了世界的一次考驗,最后剩下的 Element 不多。此世界顯得十分空曠,就給了這些存活的 Element 創建子 Element 的機會,在 Element 里實現 Create 方法,用來通過當前的 Element 創建新的 Element 對象

class Element
{public Element Create(){Element element = new Element(Random);foreach (var key in KeyList){element.KeyList.Add(key);}return element;}... // 忽略其他代碼
}

通過以上代碼可以看到,新創建的 Element 不僅繼承了用來思考的 Random 隨機數,還繼承了前輩對世界序列的思考,也就是 KeyList 元素。接下來新的 Element 可以繼續在前輩的基礎上,對世界序列進行思考

在 Manager 完成考驗,將調用 Element 的 Create 方法,讓此世界繼續被填充

class Manager
{public void Start(){... // 忽略其他代碼for (int i = 0; i < 10000; i++){... // 忽略其他代碼var currentCount = ElementList.Count;while (ElementList.Count < 10000){for (int index = 0; index < currentCount; index++){var element = ElementList[index];ElementList.Add(element.Create());}}... // 忽略其他代碼}}... // 忽略其他代碼
}

如果當前的世界考驗,干掉了絕大部分的 Element 對象,那么剩下的 Element 就有更多的機會創建出新的 Element 對象

為了防止滅世,也就是某次考驗干掉了此世界上所有 Element 小人兒,在每次迭代的時候,如果世界太過空曠,將會額外加上從空白里創建的新 Element 對象

和世界的首批 Element 一樣從石頭蹦出來的,每次迭代,都會嘗試加上一些從石頭里面蹦出來的新 Element 對象,更改后的代碼如下

class Manager
{public void Start(){... // 忽略其他代碼for (int i = 0; i < 10000; i++){... // 忽略其他代碼bool addElement = false;var currentCount = ElementList.Count;while (ElementList.Count < 10000){for (int index = 0; index < currentCount; index++){var element = ElementList[index];ElementList.Add(element.Create());}if (addElement){continue;}addElement = true;var addCount = 10000 - ElementList.Count;addCount = Math.Min(addCount, 100);for (int index = 0; index < addCount; index++){var element = CreateElement();ElementList.Add(element);}}... // 忽略其他代碼}}... // 忽略其他代碼
}

如此的進行迭代,在完成了世界的大循環,也就是 10000 次之后,將會開始最后的審判。判斷剩下的 Element 是否了解了世界序列,以及了解了多少次

class Manager
{public void Start(){... // 忽略其他代碼for (int i = 0; i < 10000; i++){... // 忽略其他代碼}for (var i = 0; i < KeyList.Count; i++){var key = GetKey(i);ElementList.RemoveAll(element => element.GetKey(i).N != key.N);}}... // 忽略其他代碼
}

最后剩下的,都是明了世界序列,也就是明了此世界本質的 Element 小人兒

完成代碼編寫之后,放入 Main 函數用來啟動世界

internal class Program
{static void Main(string[] args){Manager manager = new Manager();manager.Start();}
}

此代碼版本,放在 GitHub 上,可以從?https://github.com/lindexi/lindexi_gd/commit/49878e97df5c75c22d40294b6970aaf46b11c218?獲取全部代碼

運行代碼的結果是,最后剩下的 Element 小人兒,都明了世界序列。其實這也是因為繼承了前輩們的知識,從前輩那里拿到了 KeyList 才讓越后創建的 Element 有越高的生存率

以上是一個簡單的版本,世界序列是非常裸的參與計算,或者說沒有參與計算,就根據序列進行返回。接下來對這個世界的游戲規則加上更多的難度,應用上加法規則。加法規則就是取隨機的數值,例如 3 個數值,作為序號,再根據序號一一取出 Key 值,接著將 Key 值取和,返回一個數值。此規則同時也對每個 Element 執行,一旦發現 Element 計算出來的最終數值和世界計算出來的不匹配,那就將此 Element 淘汰

新的這個游戲規則其實對 Element 來說,更有挑戰性,也同時帶來了新的數學上的計算方法,那就是如果 Element 猜測的世界序列和此世界的世界序列不匹配,也有可能在取出的數值里面,通過加法返回相同的值。換句話說,每個 Element 在一輪迭代里面,如果沒有被淘汰,那也是無法知道當前猜測的世界序列是否正確。對比之前的規則,之前的規則,一旦猜測錯誤,自然就會被淘汰

改造一下代碼,讓 Element 和 Manager 都繼承 IKeyManager 接口,方便同時應用上相同的加法規則。這個 IKeyManager 接口定義如下

interface IKeyManager
{Key GetKey(int n);
}

加法計算規則的代碼實現如下,根據傳入參數的序列,獲取的 Key 值,取 Key 值的總和

class Manager
{private int BuildByKey(IKeyManager keyManager, IList<int> indexList){var n = 0;foreach (var index in indexList){var key = keyManager.GetKey(index);n += key.N;}return n;}... // 忽略其他代碼
}

看到這里,也許機智的大家也就猜到了。世界序列對應著世界的本源數據,而加法規則對應的通過世界本源數據進行的一套規則。有世界本源數據加上世界的本源規則,即可展現出有趣的世界。有世界的本源規則的存在,也就是此代碼世界的加法規則的存在,將會讓 Element 小人兒更加難以知道自己所了解的世界規則是對是錯

按照以上的加法規則,只要幾個 Key 相加的和相等即可,而從數學上,這是無法反算唯一解的。舉個例子,假定 indexList 里面有三個序號,分別是 1 2 3 三個序號。而 keyManager 里面根據 1 2 3 返回的 Key 分別是 10 20 30 三個 Key 值,計算出的結果是 60 的值。那反過來,已知返回值是 60 且傳入序號是 1 2 3 三個序號。請問 keyManager 存放的 KeyList 里面的第 1 和 第 2 和 第 3 的 Key 應該是多少? 抽象出來的數學題就是,已知三個數加起來的總和是 60 求這三個數。讀過小學數學的大家,自然就知道,這三個數沒有唯一解

如此加法規則,一開始就要求取序列里面的幾個 Key 值,這就要求 Element 小人兒需要一開始就初始化一段 Key 列表。否則就不好玩了。經過實際的測試結果,我發現如果不告訴 Element 小人兒 世界序列的長度 的話,那 Element 小人兒 幾乎不能在世界大循環結束之前,明了世界序列。降低游戲的難度,我將告訴 Element 小人兒 世界序列 的長度是 10 個 Key 值。同時也更改了 Element 的 BuildKey 方法,讓此方法可以在一開始就生成了序列

在之前的代碼基礎上,修改 Element 的 BuildKey 方法,本來是 BuildKey 方法每次世界迭代都會調用,現在修改為只有 Element 被創建時才調用,修改過之后的代碼如下,以下的代碼還不是最終的版本,在下文將會告訴大家最終的版本代碼

class Element
{public void BuildKey(){const int count = 10;while (KeyList.Count < count){var key = Random.Next(Key.MaxKeyValue);KeyList.Add(new Key(key));}}... // 忽略其他代碼
}

以上的代碼可以讓 Element 創建出來一段序列,序列長度和世界序列長度相同

接著從世界循環里面,刪掉每次迭代都調用 BuildKey 方法的代碼,也就是這段代碼

foreach (var element in ElementList){element.BuildKey();}

將調用 BuildKey 方法的代碼放入到 CreateElement 方法里,修改之后的方法代碼如下

class Manager
{private Element CreateElement(){Element element = new Element(new Random(Random.Shared.Next()));element.BuildKey();return element;}... // 忽略其他代碼
}

每次世界迭代都會取出隨機三個數值,將這三個隨機數值傳入到 BuildByKey 方法里,通過加法規則算出總和。將此方式分別應用在世界序列和每個 Element 上,將計算結果和世界序列計算出來的不相同的 Element 淘汰掉

實現的代碼如下,每次迭代隨機三個數值,可以先放入到一個數組里面

class Manager
{public void Start(){... // 忽略其他代碼var indexList = new int[3];for (int i = 0; i < 10000; i++){... // 忽略其他代碼}}... // 忽略其他代碼
}

每次調用 UpdateRandomIndexList 方法,將 indexList 加上三個隨機數值

class Manager
{public void Start(){... // 忽略其他代碼var indexList = new int[3];for (int i = 0; i < 10000; i++){UpdateRandomIndexList(indexList);... // 忽略其他代碼}}private void UpdateRandomIndexList(int[] indexList){for (var i = 0; i < indexList.Length; i++){indexList[i] = Random.Shared.Next();}}... // 忽略其他代碼
}

先計算世界序列經過 BuildByKey 的值

class Manager
{public void Start(){... // 忽略其他代碼var indexList = new int[3];for (int i = 0; i < 10000; i++){UpdateRandomIndexList(indexList);var key = BuildByKey(this, indexList);... // 忽略其他代碼}}... // 忽略其他代碼
}

接著依然是一句代碼,將 ElementList 里面,計算結果不等于 key 值的 Element 淘汰

class Manager
{public void Start(){... // 忽略其他代碼var indexList = new int[3];for (int i = 0; i < 10000; i++){UpdateRandomIndexList(indexList);var key = BuildByKey(this, indexList);ElementList.RemoveAll(element => BuildByKey(element, indexList) != key);... // 忽略其他代碼}}... // 忽略其他代碼
}

淘汰之后,依然就到了根據剩下存活的 Element 構建出來新的 Element 的步驟了。由于這次的 BuildKey 只有在元素創建的時候才被調用,這就意味著需要改造 Create 方法,讓 Element 的在創建時調用 BuildKey 方法,修改之后的代碼如下

class Element
{public Element Create(){Element element = new Element(Random);foreach (var key in KeyList){element.KeyList.Add(key);}element.BuildKey();return element;}... // 忽略其他代碼
}

而根據以上的 BuildKey 方法的代碼,只是將 KeyList 序列生成到 10 個,顯然不符合當前的需求。畢竟現在在創建的時候,就設置了 KeyList 內容了,這會讓 BuildKey 方法啥都沒有做。 繼續優化 BuildKey 方法,讓此方法可以將 KeyList 進行更改

class Element
{public void BuildKey(){const int count = 10;while (KeyList.Count < count){var key = Random.Next(Key.MaxKeyValue);KeyList.Add(new Key(key));}KeyList[Random.Next(count)] = new Key(Random.Next(Key.MaxKeyValue));}... // 忽略其他代碼
}

以上代碼就是優化完成之后的 BuildKey 方法。大概映射的含義就是,子 Element 可以從前輩繼承到 KeyList 知識,只是子 Element 要做出變化,變化就是修改 KeyList 中的數據。當前的變化只是修改一項而已

更改完成之后,即可開始跑代碼。當前的代碼的含義總的來說就是,在此世界里面,有一段世界序列,世界規則將根據世界序列計算出一個值,同樣的世界規則也使用相同的算法應用在每個 Element 小人兒上,一旦發現兩者計算結果不相同,那么 Element 小人兒將被淘汰。存活下來的 Element 小人兒將可以創建出下一代 Element 小人兒出來,創建的時候,可以將自己的知識傳授給下一代。而下一代 Element 小人兒也不是全盤接受的,而是會經過自己的思考,優化從前輩繼承到 KeyList 知識

只不過呢,在此世界里面,世界規則只是一個加法規則。而下一代 Element 小人兒的思考也只是一段隨機數

嘗試運行程序,可以看到這一次滅世的情況發生的次數比一開始的代碼的多。滅世的情況就是在世界的某一代中,存活下來的 Element 小人兒的數量是 0 個。可以看到當前代碼的規則讓 Element 小人兒更加難以應對。但也同時發現了這樣的規律,一旦開始有某個 Element 小人兒掌握了一定數量的正確的世界序列的值時,此 Element 小人兒將可以創建出更多更好存活的下一代 Element 小人兒

舉個例子來說明運行的情況

假定世界序列就是從 0 到 9 的 10 個 Key 數值。某個 Element 掌握的序列就是 1020120120 序列。剛好一開始的 indexList 就是取前三個,這就讓 Element 存活起來了。于是接下來 Element 將創建出下一代的 Element 出來。下一代的 Element 剛好修改的第 3 個(從0開始)序號為 4 的值,修改之后的是 1024120120 序列。下一輪世界取的 indexList 是 1 2 3 三個序號,世界序列計算結果是 1+2+3=6 的值。而原先的 Element 計算出來的是 0+2+0=2 被淘汰,而下一代的 Element 計算出來的是 0+2+4=6 存活。可以看到,盡管下一代的 Element 沒有思考出正確的世界序列,然而在世界規則的處理下,依然還是可以存活的,只不過在偏離世界序列的情況下,可以存活的代數自然是有限的

這也能說明能存活下來的 Element 前輩掌握的世界序列是有一定的正確性的,但是下一代的 Element 是不知道前輩有哪些序列是正確的,甚至前輩的 KeyList 都是偏離世界序列的,只是剛好滿足當前的世界規則而存活

在經過了世界大循環之后,可以再來看看存活下來的 Element 小人兒掌握世界序列的情況。這次的結果是絕大部分的 Element 小人兒掌握了正確的世界序列,之后少部分的 Element 小人兒掌握了錯誤的世界序列。這些少部分的掌握錯誤的世界序列的 Element 小人兒都是在最后幾代世界循環里面創建的。也就是說活的足夠久的 Element 小人兒都是掌握了正確的世界序列的

這也能映射到現實世界的一部分,能夠存活下來的生物,或者人,都是掌握了一定的世界序列,也就是世界本源或者說世界的知識,或者說是符合世界規則。掌握的越多,或者說行為越靠近世界規則,就越能存活

此代碼版本,放在 GitHub 上,可以從?https://github.com/lindexi/lindexi_gd/commit/5f7d17b206b904db424d17fed6cef48eb0965496?獲取全部代碼

這個代碼游戲到這里還沒有結束,可以玩的還有很多。例如修改下一代的 Element 的思考邏輯,讓下一代的 Element 更加有想法,想要更改更多的知識。在修改之后的代碼世界,下一代的 Element 更加質疑前輩的知識,會更多的思考世界序列,而不是和之前的代碼一樣,只是修改世界序列里面的一項

修改之后的代碼如下

class Element
{public void BuildKey(){const int count = 10;while (KeyList.Count<count){var key = Random.Next(Key.MaxKeyValue);KeyList.Add(new Key(key));}var updateCount = Random.Next(1, count);for (int i = 0; i < updateCount; i++){KeyList[Random.Next(count)] = new Key(Random.Next(Key.MaxKeyValue));}}... // 忽略其他代碼
}

運行一下代碼,可以看到此時運行的情況是,在很多代的世界大循環里面,即世界代數里,大量存在滅世的情況。因為下一代的 Element 小人兒思考越多,代表著繼承到的前輩的知識越少。繼承的知識越少,越難以存活。這也能說明前輩們的知識是有用的

此代碼版本,放在 GitHub 上,可以從?https://github.com/lindexi/lindexi_gd/commit/9bb128484abfa9fe6f5ba3ff66a91505fb3105b5?獲取全部代碼

好了,今天的小測試就到這里。通過這個代碼故事可以告訴咱,在這個代碼世界里面,是符合天有五賊,見之者昌的道理,越接近世界序列的 Element 小人兒將越能存活。這個和當前的現實世界也差不多

在這個代碼世界里面,前輩的知識是有用的,學習前輩的知識可以更好幫助存活,符合書籍是人類進步的階梯這句話的道理。通過讓前輩的知識傳授給下一代,可以逐漸讓整個世界在一代一代的循環里面存活的 Element 小人兒的數量越多

在此代碼世界里面,前輩傳授給下一代的知識也不一定是完全正確的,下一代需要進行質疑,因為前輩說不定活不過世界的下次迭代,前輩的知識只是剛好在當前的世界規則下是正確的,不代表著在下一次迭代的世界規則還是正確的。映射到現實世界,那就是需要質疑前輩的知識,前輩的知識放在前輩的時代是正確的,不代表在當前也是正確的。但是將前輩們的知識全拋掉,那自然也是不對的

現實世界里面也許存在世界序列和世界規則,然而現實世界里面可不會告訴大家,有多少個世界序列列表,世界序列的每個項的取值范圍是多少,世界序列有多長等。試試在代碼世界里面,讓代碼世界的世界序列的取值范圍更大,或者是世界序列更長,試試看修改之后的滅世次數。同樣現實世界不會告訴大家世界規則是什么,有多少個規則。現實世界的世界序列和世界規則更加復雜,這就讓在現實世界進行探索世界的本質更加難。但是有一點是正確的,那就是學習前輩們的知識同時進行自己的思考,在一代代的努力下,可以不斷靠近世界的本質

這個代碼世界還有很多可以玩的,例如可以修改更有趣的世界規則,也就是 BuildByKey 方法。修改 Element 的思考方式等

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/279863.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/279863.shtml
英文地址,請注明出處:http://en.pswp.cn/news/279863.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python 批量修改密碼

下午閑來無事&#xff0c;就搞個批量密碼修改工具玩玩... #!/usr/bin/env python import paramiko import time ip_list(ip1,ip2) log_fileopen(mpwdok.log,w) log_file1open(mpwderr.log,w) for ip in ip_list: try: s paramiko.Transport((ip, 22)) s.c…

如何在Android Wear上節省電池壽命

If you’re rocking Android on your wrist, there’s a chance you’ve learned to rely on its convenience pretty heavily. And if you’re in that position, then you probably also know how annoying it can be if your watch runs out of juice in the middle of the …

css3 偽類選擇器

1.target&#xff1a;表示當前的url片段的元素類型&#xff0c;這個元素必須是E &#xff08;作用類似于選項卡&#xff09; 2.&#xff1a;&#xff1a;before{content&#xff1a;“要添加的內容”} 添加到......之前 3.rgb&#xff08;&#xff09; 顏色 4.rgba&#xf…

城市統計【BFS】

題目大意&#xff1a; 中山市的地圖是一個n*n的矩陣&#xff0c;其中標號為1的表示商業區&#xff0c;標號為0的表示居民區。為了考察市內居民區與商業區的距離&#xff0c;并對此作出評估&#xff0c;市長希望你能夠編寫一個程序完成這一任務。  居民區i到商業區的距離指的是…

使用 DataAnnotations(數據注解)實現通用模型數據校驗

.net 跨平臺參數校驗的意義在實際項目開發中&#xff0c;無論任何方式、任何規模的開發模式&#xff0c;項目中都離不開對接入數據模型參數的合法性校驗&#xff0c;目前普片的開發模式基本是前后端分離&#xff0c;當用戶在前端頁面中輸入一些表單數據時&#xff0c;點擊提交按…

網線的做法 及 POE的介紹

網線的做法 以太網線采用差分方式傳輸。所謂差分方式傳輸&#xff0c;就是發送端在兩條信號線上傳輸幅值相等相位相反的電信號&#xff0c;接收端對接受的兩條線信號作減法運算&#xff0c;這樣獲得幅值翻倍的信號。其抗干擾的原理是&#xff1a;假如兩條信號線都受到了同樣&am…

unity 使用tile_如何使用Tile從網上查找電話

unity 使用tileTile is a fantastic little gadget that can help you find your lost keys or wallet. However, it can also locate and ring your phone, even if you never buy a single physical Tile. Here’s how to find your lost phone using the Tile app on the we…

你與一份好簡歷之間的距離

閱讀本文大概需要 2.7 分鐘。每年年初都是企業的招聘旺季&#xff0c;對應的三四月份絕對跳槽、找工作的好時機&#xff0c;業內經常稱呼這兩個月為金三銀四。實力雄厚的人&#xff0c;那個月找工作問題都不大&#xff0c;但是也會盡量挑選個好時機&#xff0c;能有更多的選擇。…

Python 循環刪除指定文件夾下所有的.longtian類型文件

# -*- coding: utf-8 -*-import os#遍歷文件夾刪除文件 def traversing_dir(rootDir):#遍歷根目錄for root,dirs,files in os.walk(rootDir):for file in files:#文件后綴名extFileos.path.splitext(file)[1]if extFile".longtian":os.remove(os.path.join(root,file…

《ASP.NET Core 6框架揭秘實例》演示[35]:利用Session保留語境

客戶端和服務器基于HTTP的消息交換就好比兩個完全沒有記憶能力的人在交流&#xff0c;每次單一的HTTP事務體現為一次“一問一答”的對話。單一的對話毫無意義&#xff0c;在在同一語境下針對某個主題進行的多次對話才會有結果。會話的目的就是在同一個客戶端和服務器之間建立兩…

Vincross孫天齊:人機界面的突破將引發科技革命

8月23—27日&#xff0c;世界機器人大會在北京舉辦&#xff0c;全球各國機器人領域的優秀企業悉數亮相&#xff0c;五花八門的機器人及產業鏈上下游最新技術均能在這次盛會上找到蹤跡&#xff0c;整個會場充滿了未來感與時代發展的氣息。 大會中智慧城市服務機器人技術與應用專…

如何在Windows上使用64位Web瀏覽器

Google and Mozilla now offer 64-bit versions of Chrome and Firefox for Windows. Here’s how to find out what version you’re running and how to upgrade. Google和Mozilla現在提供適用于Windows的64位版本的Chrome和Firefox。 這是找出正在運行的版本以及如何升級的方…

立下“去O”Flag的AWS,悄悄修煉了哪些內功?

AWS re:Invent 2018大會上&#xff0c;AWS首席執行執行官Andy Jassy 表示到 2019 年底&#xff0c;亞馬遜將全面放棄使用 Oracle 數據庫&#xff0c;97&#xff05;的“關鍵任務數據庫”將運行在亞馬遜自己的數據庫服務上。 如今&#xff0c;2019年已經過去了四分之一&#xff…

static作用:靜態變量的生存周期和作用域

首先要理解生存周期與作用域的區別&#xff1a; 生存周期: 變量從定義到銷毀的時間范圍。存放在全局數據區的變量的生存周期存在于整個程序運行期間&#xff0c;而存放在棧中的數據則隨著函數等的作用域結束導致出棧而銷毀&#xff0c;除了靜態變量之外的局部變量都存放于棧中…

劉強東痛批京東高管,拿PPT騙他!網友怒了:愛用 PPT 忽悠的人,他們都遭人痛恨...

這是頭哥侃碼的第272篇原創因為被新冠感染&#xff0c;所以最近兩周都在休養。前幾天&#xff0c;我無意中看到一則有關劉強東的新聞&#xff0c;大致是他在京東內部管理培訓會上痛批部分高管&#xff0c;稱 “拿PPT和假大空詞匯忽悠自己的人就是騙子”&#xff0c;表示部分高管…

關于file的部分簡單命令

1.關于file的簡單命令 2.創建/刪除 文件/目錄 ## -f和-r可以連用&#xff0c;表示強制刪除 3.文件/目錄的復制 ##復制是一個新建的過程&#xff0c;在保持原有不變的基礎上重新再建立一個 4.文件/目錄的移動 ##移動是一個重命名的過程&#xff0c;但不改變其中的內容 本文轉自…

字節與浮點型轉換軟件_如何與另一個防病毒軟件一起運行惡意軟件字節

字節與浮點型轉換軟件Malwarebytes Anti-Malware is a great security tool that’s particularly effective against “potentially unwanted programs (PUPs)” and other nasty software traditional antivirus programs don’t deal with. But it’s intended to be used a…

vsftpd服務的搭建

1.vsftpd介紹vsftpd&#xff1a;是非常安全的ftp守護進程(Very secure ftp Daemon)。進程&#xff1a;正在進行&#xff08;運行running&#xff09;的程序。守護進程Daemon&#xff1a;網絡服務類的程序都會有守護進程。守護進程是指實時監測服務訪問狀態的程序。通常都是在系…

火狐瀏覽器書簽(收藏夾)全部消失,歷史記錄也消失,如何恢復

今天關閉再打開火狐瀏覽器瞬間懵逼&#xff0c;瀏覽器所有的記錄都沒了&#xff0c;映入眼簾的的火狐新手指導頁&#xff0c;而且主頁導航變成了hao123&#xff0c;我估計是外部程序篡改了瀏覽器配置&#xff0c;或者其他異常導致瀏覽器重置。書簽、歷史記錄對開發人員的重要性…

apple tv 開發_如何防止Apple TV進入睡眠狀態

apple tv 開發Your Apple TV, by default, goes to sleep fairly quickly when not in use. That’s great for power saving but not so great if you like to keep it on. Let’s take a look at how to extend how long it stays awake or disable sleep mode altogether. 默…