網路教學與日常學習
網路教學與日常學習
GNS3安裝與設定教學(2.2.10) ※疑難:GNS3無法順利連上VM。(VMware Player)
第一步:下載 GNS3
![]() |
| 下載 GNS3 |
第二步:安裝 GNS3
![]() |
| 一路按「Next」或「I Agree」 |
![]() |
| 如果沒有VM檔的可以勾選,可以先把VM檔下載回來,但一般不用勾。 至於Tools,新手全勾選,有些是必須安裝才能順利使用。 |
| 官方對於Tools的簡短敘述 |
![]() |
| 選一個VM Type的VM檔 (個人建議選 VMware Workstation) |
第三步:設定 GNS3
![]() |
| 首次進入GNS3,會看到這個畫面。 |
![]() |
| 沒有特別需求就按「Next >」 |
![]() |
| 需要先在VM Software匯入VM檔才能下一步 ※CPU數跟記憶體預設為 1、2048MB,VM檔預設也是如此,二者建議相同。 若第一次用就不去改參數,因為用預設下,二者也會一致。 |
如果是新手,而且又用「VMware Workstation Player」的,接下來是
「十分重要」
![]() |
| VM進入「Test」測試,就可以知道VM是否能上網。 |
疑難雜症區
GNS3無法順利連上VM。(VMware Player)
![]() |
| 打開GNS3,GNS3也順利執行VM,但發現VM不通 |
![]() |
| 拖曳 Cloud 跟 VPCS (在 local server) 對 Cloud 按右鍵點 Console |
![]() |
| 勾選「Show special Ethernet interfaces」 然後上方切到「VMware Network Adapter WMnet1」 點「Add」 |
![]() |
| 按下OK後,把 PC1 跟 Cloud 的 VMnet1 接起來。 |
![]() |
| 啟動PC1,然後進入Console |
![]() |
| 這時用「CMD」打「ipconfig」去查「VMnet1」的位置 參考並選一個IP位置要做為PC1的IP位置。 (不知道的可以拿尾碼加1,此例為10.1.1.4) |
![]() |
| 設定IP位置,並 嘗試Ping VMnet1(位置在ipconfig可查) 嘗試Ping VM(寫在VM的資訊頁) |
Leetcode題解 Python & C#六月挑戰DAY20 Permutation Sequence
Python
class Solution:
def getPermutation(self, n: int, k: int) -> str:
result = ""
nums = [str(i) for i in range(1, n+1)]
method = [1]
for i in range(1, n):
method.append(method[i-1]*i)
k -= 1
for i in range(n-1, 0, -1):
result += nums.pop(k // method[i])
k = k % method[i]
result += nums.pop()
return result
C#
public class Solution {
public string GetPermutation(int n, int k) {
var result = new List();
var number = new List();
var factorial = new int[9];
factorial[0] = 1;
for(int i = 1; i < n; i ++)
{
factorial[i] = factorial[i-1]*i;
number.Add(i);
}
number.Add(n);
k -= 1;
for(int i = n-1; i > 0; i--)
{
result.Add(number[k / factorial[i]]);
number.RemoveAt(k / factorial[i]);
k = k % factorial[i];
}
result.Add(number[0]);
return string.Join("", result);
}
}
Leetcode題解 Python:六月挑戰DAY19 Longest Duplicate Substring
Python
class Solution:
def longestDupSubstring(self, S: str) -> str:
hashMap = dict()
count = 0
nums = []
for c in S:
if c not in hashMap:
hashMap[c] = count
count += 1
nums.append(hashMap[c])
mod = 2**64
def search(length):
SubStrHash = 0
for i in range(length):
SubStrHash = (SubStrHash*count + nums[i])%mod
hashset = {SubStrHash}
al = (count**length)%mod
for i in range(length, n):
SubStrHash = (SubStrHash*count - nums[i-length]*al + nums[i])%mod
if SubStrHash in hashset:
return i
hashset.add(SubStrHash)
return -1
n = len(S)
l, r = 0, n
end = -1
while r > l:
m = (r - l)//2 + l
res = search(m+1)
if res == -1:
r = m
else:
l = m + 1
end = res
return "" if end == -1 else S[end - r + 1: end+1]
Leetcode題解 Python & C#:六月挑戰DAY18 H-Index II
Python
class Solution:
def hIndex(self, citations: List[int]) -> int:
if not citations: return 0
n = len(citations)
l, r = 0, n
while l < r:
m = (r-l)//2 + l
if citations[m] >= n-m:
r = m
else:
l = m + 1
return n-r
C#
public class Solution {
public int HIndex(int[] citations) {
int l = 0;
int r = citations.Length;
while(l < r)
{
int m = (r-l)/2 + l;
if(citations[m] >= citations.Length - m)
r = m;
else
l = m + 1;
}
return citations.Length - r;
}
}
testcase
[100]
[]
[1]
[0,1,3,5,6]
[0,1,2,5,6]
Wildcard Mask 用Python計算去簡化輸入
Repl.it (線上執行Python) ※支援手機(Android IOS)OneWildcardMask: 將輸入的IP位置用一組Network和WildcardMask表示。MultiWildcardMask: 用一或多組Network和WildcardMask去表示所有輸入的IP的。
"""
ips間互相做XOR得到結果一
再把結果一做OR,得到單一最低限度的wildcard mask
"""
ips = [[192,168,0,7], [192,168,0,15]]
result = [set(), set(), set(), set()]
wc = []
# 兩兩 XOR => 計算結果1
for i1 in range(len(ips)-1):
for i2 in range(i1+1, len(ips)):
for i3 in range(4):
result[i3].add(ips[i1][i3] ^ ips[i2][i3])
# 計算結果1 做 OR 總計算
for i in range(4):
num = 0
for res in result[i]:
num |= res
wc.append(num)
print(wc)
"""
再次簡化
"""
ips = [[192,168,0,7], [192,168,0,15]]
wc = [0, 0, 0, 0]
for i1 in range(len(ips)-1):
for i2 in range(i1+1, len(ips)):
for i3 in range(4):
wc[i3] |= (ips[i1][i3] ^ ips[i2][i3])
print(wc)雖然算得出來,但是因為一開始要算兩兩成對XOR,所以會至少要算 n(n-1)/2 次,如果要把一個範圍納入,如最後二位可[0, 255]間,會計算(255*255)*((255*255)-1)/1次。那會運算相當久,但對人來說,那可能是一秒就能算完的。換個想法,既然在IP位置清單內的都要能符合,不如從一個 (Network, Wildcard) 的組合,對應每一個IP位置去做一些修改,讓每一個都能符合條件。
ips = []
for l1 in range(256):
for l2 in range(256):
ips.append([192, 168, l1, l2])
wc = [[[0,0,0,0], [255,255,255,255]]]
if ips:
wc = [[ips.pop(0), [0,0,0,0]]]
for ip in ips:
for i in range(4):
wc[0][1][i] |= wc[0][0][i] ^ ip[i]
print(wc)
=> [[[192, 168, 0, 0], [0, 0, 255, 255]]]
"""
給一串可以預期整理成下方結果的IP
Network: 192.168.0.0, Wildcard Mask: 0.0.0.3
Network: 192.168.0.4, Wildcard Mask: 0.0.0.8
"""
ips = [[192,168,0,0],[192,168,0,1],[192,168,0,2],[192,168,0,3],[192,168,0,4],[192,168,0,12]]
from collections import defaultdict
wc = defaultdict(list)
"""
將 IP位置 做 summary
"""
def check(strIP, strIP2):
"""
只能有一個位置01同時出現
但如果是 * 符,二者沒有對上,就表示無法整合。
"""
dismatch = 0
pos = -1
for i in range(32):
if strIP[i] != strIP2[i]:
if strIP[i] == "*" or strIP2[i] == "*": return -1
dismatch += 1
pos = i
if dismatch == 2: return -1
return pos
for ip in ips:
strIP = "{:0>8}{:0>8}{:0>8}{:0>8}".format(*[bin(num)[2:] for num in ip]) # 換成 連續二進位 string
level = 0
pos = 0
while pos != -1 and wc[level]:
for j in range(len(wc[level])):
pos = check(strIP, wc[level][j][1])
if not pos == -1:
ip = wc[level].pop(j)[0]
strIP = strIP[:pos] + "*" + strIP[pos+1:]
level += 1
break
wc[level].append([ip, strIP])
"""
將 Summary 後的結果轉換回十進位格式
"""
result = []
for key in wc:
for NW in wc[key]:
NW[1] = NW[1].replace("1", "0").replace("*", "1")
result.append([NW[0], [int(NW[1][0:8],2), int(NW[1][8:16],2),int(NW[1][16:24],2),int(NW[1][24:32],2)]])
"""
將十進位的資料型態換成字串
"""
for each in sorted(result):
Network = ".".join([str(num) for num in each[0]])
WildcardMask = ".".join([str(num) for num in each[1]])
print("Network: {:}, Wildcard Mask: {:}".format(Network, WildcardMask))
Leetcode題解 Python & C#:六月挑戰DAY17 Surrounded Regions
Python
class Solution:
def solve(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
if not board or not board[0]: return
excludePos = set()
rows = len(board)
cols = len(board[0])
def searchExclude(y, x):
if y = rows: return
if x = cols: return
if board[y][x] == "O" and (y,x) not in excludePos:
excludePos.add((y,x))
searchExclude(y-1, x)
searchExclude(y+1, x)
searchExclude(y, x-1)
searchExclude(y, x+1)
for y in range(rows):
searchExclude(y, 0)
searchExclude(y, cols-1)
for x in range(cols):
searchExclude(0, x)
searchExclude(rows-1, x)
for x in range(1, cols-1):
for y in range(1, rows-1):
if board[y][x] == "O" and (y,x) not in excludePos:
board[y][x] = "X"
C#
public class Solution {
public int rows;
public int cols;
public HashSet excludePos;
public void Solve(char[][] board) {
rows = board.Length;
if(rows == 0){return;}
cols = board[0].Length;
if(cols == 0){return;}
excludePos = new HashSet();
for(int y = 0; y < rows; y++)
{
SearchExcluded(board, y, 0);
SearchExcluded(board, y, cols-1);
}
for(int x = 0; x < cols; x++)
{
SearchExcluded(board, 0, x);
SearchExcluded(board, rows-1, x);
}
for(int y = 0; y < rows; y++)
{
for(int x = 0; x < cols; x++)
{
if(board[y][x] == 'O' && !excludePos.Contains((y, x)))
{
board[y][x] = 'X';
}
}
}
}
public void SearchExcluded(char[][] board, int y, int x) {
if(y = rows){return;}
if(x = cols){return;}
if(board[y][x] == 'O' && !excludePos.Contains((y, x)))
{
excludePos.Add((y, x));
SearchExcluded(board, y-1, x);
SearchExcluded(board, y+1, x);
SearchExcluded(board, y, x-1);
SearchExcluded(board, y, x+1);
}
}
}
JN的CCNA: 如何使用
這裡依照 《CCCNA 200-301 Official Cert Guide》 這本書的目錄做章節的分類,這使得照這裡的步驟去學習是與官方指南是一致的。所以只要一回回都確實完成,就能含蓋所有範圍。
每個章節(Charpter)可以分成三個部分︰
「學習內容」:
如果有書籍或其他來源沒有寫仔細的部分,我就會補充,否則只會放上出處。這裡會按照推薦順序排列,越好的會排在前面,多寡不一定,但最少一定會有書籍。
「實作練習」:
搭配《Cisco Packet Tracer》作練習,使用的版本為「7.3」。實作可分為二種:解說型、演練型。解說型主要目的為配合當節內容作「觀察」,注重各時刻的狀況變化;演練型的會有幾種:單項設定、除錯、多項設定、設計。每個演練型的最後都要完成一些要求,如:ping通,或是切斷部分仍能正常運作。
「相關題目」:
會把題庫中相關的題目放到這裡, 針對考題內容作實作(如果有辦法的話)。
我建議每個章節分三個狀態,然後自己紀錄下來進度,確保每個部分都有完成。
JN的CCNA: 對學習CCNA的看法
前言 – – 對學習CCNA的看法 2020.06.13
我在 2020-06-12 考到了 CCNA 的證照。
有人覺得 CCNA 的證照很好考,也許是,因為只要把「題庫」背熟,背多分,就能考過。但能考過是一回事,要考滿分又是另外一回事。2020年改版的CCNA題庫,因為還不成熟,各家答案並不一致,所以要是沒有強大的「實作」能力,只背是不可能明暸前因後果,找到一個能信服自己的答案(但不一定是正確的)。
總之,如果在台灣考,選用某中文論壇(hh)的題庫,正確率高,範圍精準,品質也好。但是我覺得還是有美中不足的地方,就是有一些關鍵敘述是漏掉的,那會「嚴重」影響解題。這現象在各版現有我看過的題庫,都有出現。
我認為不必花錢買題庫,因為不能保障買到的品質,更不能買到自己到題目會有深刻的理解。只有腳踏實地,一個個篇章逐一擊破,拿到證書才能稱上實質合格的CCNA。
CCNA的考試範圍是很大的,官方書籍(ccna certification study guide)的頁數總和就有千頁以上!新版合併各範圍成一個 200-301,因此也把各範圍拉一些到書的後面章節,分數也佔了不少。那些篇章不是 router & switch ,就好像從頭從零開始,然後多半又屬於記憶性的。先不說能看完就算厲害的,但看完只是入門,不夠,需要實作,
講這麼多,我認為CCNA是需要很多時間去精熟的,培訓課程開66小時,但那只夠把要上的都粗略講一遍,除非夠聰明,不然很難一次就照單全收,且能夠互相搭配運用。除了上課之外,練習也是很重要的,大概也要再花66小時去練實作,實作會學到的跟用到的可能是CCNP或是CCIE級別的深度。這裡的實作不只是單一項目的設定,也可能包含一些情境式的設計,或是效率優化的配置,那會用到許多CCNA會講到的協定,使根基更穩固。
我也是有上班級的,課餘花了很多時間去探索那些CCNA範圍內的知識與其運作。有CCNA證照不代表那些該會的能做得出來,懂不懂,那一眼就看得出來。CCNA並不限制一定要上他們合作機構的課程才能考試,所以課程沒上完就能考證照,沒上課也可以考試。
有證照一定是加分,會做是門檻,「會不會做才是關鍵」。
真實的工作情況大部分都是TroubleShooting,而也只有多練,過程自己一定會有不小心(遺漏或打錯),思考可能是哪裡出了錯,去找出那些問題,並且解決掉,才有辦法去往高階去創建或維護大型且複雜的網路。
看到一些同學在練習時,一臉盲然,努力回想上次老師講了什麼指令,然後重頭輸入。他們學習充滿了挫折感,因為不知為何。一個「不小心」,就連TroubleShooting的能力都沒有,呆坐電腦前,因為他們的腦內世界沒有TroubleShooting指令,只有上課講到的指令。
這樣的學習方式是大錯特錯,我並不是嘲諷那些人或教學方式的死板,而且老師教得不錯。
「輸入指令絕對不是第一步!」
要先有一個期望或設計(目的地),然後再想說要輸什麼指令(決定交通方式),再輸入指令(前往目的地),檢查(有沒有到達正確的地方)。這也是寫程式語言的標準流程。
那些學得挫折的同學,大多都沒有第一步的概念,也沒有第二步的思考與選擇,所以連去哪都不清楚,自己在搭乘什麼也不清楚,當然,所以自己此時此刻身處何方是沒有概念的,內心可能有這種感受「我是誰?我在哪?我在幹嘛?」
又或者沒有能區分「設計」與「設定」的對錯。
「設計」沒有對錯,除非是不合規則的(如router二介面設計在同一網段)。
而「設定」是跟隨設計,設定才會有明顯的對錯分別,沒照設計或是不合規則就是錯的。
能夠按設計圖施工,設定完成一個結構的人,才是「工程師」。如果每一步都要等人發號施令,那只是「工人」。這也使我在教同學時,到底要把所有指令全講,或是提示部分讓他思考,最終培育出不同程度的能力。
總之,要培養一個明確的思維思路,我都稱之「程式邏輯」。難的不是指令背不起來,而是沒辦法想到與制定一個如SOP一步一步的概念,要是能想到,指令再補上,就套方法可以用到許多領域。
最後,我的目標是「CCIE」,而且還想要有二張,因此,
關於CCNA或CCNP的學習頁面會一直作整理(更新)直到我考完CCIE第二張的半年。
這是我的規劃,在這期間內,如果有任何問題或更新,我會「Best Effort」去做,要是有幫上忙,就給個支持或留個言。
Leetcode題解 Python & C#:六月挑戰DAY16 Validate IP Address
Python
class Solution:
def validIPAddress(self, IP: str) -> str:
deci = {*"0123456789"}
hexdeci = {*"0123456789abcdef"}
def checkIPv4(IP):
group = IP.split(".")
if len(group) != 4: return False
for seg in group:
if not(3 >= len(seg) >= 1): return False
if any([c not in deci for c in seg]): return False
if not(255 >= int(seg) >= 0): return False
if str(int(seg)) != seg: return False
return True
def checkIPv6(IP):
group = IP.lower().split(":")
if len(group) != 8: return False
for seg in group:
if not(4 >= len(seg) >= 1): return False
if any([c not in hexdeci for c in seg]): return False
return True
if checkIPv4(IP): return "IPv4"
if checkIPv6(IP): return "IPv6"
return "Neither"
Python(IP轉換版)
class Solution:
def validIPAddress(self, IP: str) -> str:
decimal = {*"0123456789"}
def covertIPv4(IP):
IPv4 = ""
seg = ""
segCount = 0
for c in IP:
if c == ".":
segCount += 1
if segCount >= 4 or not seg: return False
if len(seg) > 1 and seg[0] == '0': return False
seg = "{:0>8}".format(bin(int(seg))[2:])
if len(seg) > 8: return False
IPv4 += seg
seg = ""
elif c in decimal:
seg += c
else:
return False
if seg:
if len(seg) > 1 and seg[0] == '0': return False
seg = "{:0>8}".format(bin(int(seg))[2:])
if len(seg) > 8: return False
IPv4 += seg
return len(IPv4) == 32
hexadecimal = {*"0123456789abcdefABCDEF"}
def covertIPv6(IP):
IPv6 = ""
seg = ""
segCount = 0
for c in IP:
if c == ":":
segCount += 1
if segCount >= 8 or not seg: return False
seg = "{:0>16}".format(seg)
if len(seg) > 16: return False
IPv6 += seg
seg = ""
elif c in hexadecimal:
seg += "{:0>4}".format(bin(int(c, 16))[2:])
else:
return False
if seg:
seg = "{:0>16}".format(seg)
if len(seg) > 16: return False
IPv6 += seg
return len(IPv6) == 128
if covertIPv4(IP): return "IPv4"
if covertIPv6(IP): return "IPv6"
return "Neither"
Python(IP轉換合一版)
class Solution:
def validIPAddress(self, IP: str) -> str:
decimal = {*"0123456789"}
hexadecimal = {*"0123456789abcdef"}
def covertIP(strIP, Segs, PerSegBit, Carry, Delimiter):
def addSeg(IP, seg):
if segCount >= Segs or not seg: return False
if Delimiter == "." and len(seg) > 1 and seg[0] == '0': return False
if Delimiter == ":" and len(seg) > 4: return False
try:
seg = ("{:0>"+str(PerSegBit)+"}").format(bin(int(seg, len(Carry)))[2:])
except:
return False
if len(seg) > PerSegBit: return False
return IP + seg
IP = seg = ""
segCount = 0
for c in strIP.lower():
if c == Delimiter:
segCount += 1
IP = addSeg(IP, seg)
if not IP: return False
seg = ""
elif c in Carry:
seg += c
else:
return False
if not seg: return False
IP = addSeg(IP, seg)
if not IP: return False
return len(IP) == Segs * PerSegBit
if covertIP(IP, 4, 8, decimal, "."): return "IPv4"
if covertIP(IP, 8, 16, hexadecimal, ":"): return "IPv6"
return "Neither"
C#
public class Solution {
public string ValidIPAddress(string IP) {
if(IsIPv4(IP)){return "IPv4";}
if(IsIPv6(IP)){return "IPv6";}
return "Neither";
}
private bool IsIPv4(string IP) {
var parts = IP.Split('.');
if(parts.Length != 4){return false;}
int dec = 0;
foreach(var part in parts)
{
if(!(Int32.TryParse(part, out dec))){return false;}
if(dec 255 || (dec.ToString().Length != part.Length)){return false;}
}
return true;
}
private bool IsIPv6(string IP) {
var parts = IP.Split(':');
if(parts.Length != 8){return false;}
int hex;
foreach(var part in parts)
{
if(part.Length > 4){return false;}
if(!Int32.TryParse(part,
System.Globalization.NumberStyles.HexNumber,
null,
out hex)){return false;}
if(hex < 0){return false;}
}
return true;
}
}
TestCase
"1.1.1.01"
"01.01.01.01"
"001.001.001.001"
"301.301.301.301"
"12..33.4"
"1.0.1."
"1.-1.1.1"
"0.0.0.0"
"172.16.254.1"
"256.256.256.256"
"2001:0db8:85a3:0:0:8A2E:0370:7334"
"2001:0db8:85a3::8A2E:0370:7334"
"2001:db8:85a3:0:0:8A2E:0370:7334"
"20EE:FGb8:85a3:0:0:8A2E:0370:7334"
"2001:0db8:85a3:00000:0:8A2E:0370:7334"
"1081:db8:85a3:01:-0:8A2E:0370:7334"
"2001:0db8:85a3:0:0:8A2E:0370:7334:"
Leetcode題解 Python:Maximum Frequency Stack
Python
class FreqStack:
def __init__(self):
self.count = defaultdict(int)
self.freq = defaultdict(list)
self.MaxFreq = 0
def push(self, x: int) -> None:
self.count[x] += 1
self.freq[self.count[x]].append(x)
self.MaxFreq = max(self.MaxFreq, self.count[x])
def pop(self) -> int:
num = self.freq[self.MaxFreq].pop()
self.count[num] -= 1
if not self.freq[self.MaxFreq]: self.MaxFreq -= 1
return num
Leetcode題解 Python & C#:Maximum Binary Tree
1.The root is the maximum number in the array.
2.The left subtree is the maximum tree constructed from left part subarray divided by the maximum number.3.The right subtree is the maximum tree constructed from right part subarray divided by the maximum number.
Python
class Solution:
def constructMaximumBinaryTree(self, nums: List[int]) -> TreeNode:
if not nums: return None
maxIdx = nums.index(max(nums))
return TreeNode(nums[maxIdx], self.constructMaximumBinaryTree(nums[:maxIdx]), self.constructMaximumBinaryTree(nums[maxIdx+1:]))
C#
public class Solution {
public TreeNode ConstructMaximumBinaryTree(int[] nums) {
if(nums.Length == 0){return null;}
int maxIdx = Array.IndexOf(nums, nums.Max());
return new TreeNode(nums[maxIdx],
ConstructMaximumBinaryTree(nums.Take(maxIdx).ToArray()),
ConstructMaximumBinaryTree(nums.Skip(maxIdx+1).Take(nums.Length-maxIdx+1).ToArray()));
}
}



















