프로그래머스 '다리를지나는 트럭' 다른 풀이방법을 봐도 어떻게 풀었는지 바로 이해가 안가서 내 방법대로 겨우 풀었다.... 똑똑한 사람 왜이렇게 많음..

 

  • 내 방법

time 이라는 리스트를 만들어 현재 지나가고 있는 트럭의 시간을 함께 기록함으로써 시간체크를 한다.

ing와 time은 같은 index끼리 매칭 되어서 시간을 체크한다.

bridge_length = 2

ing = [4,5]

time = [2,1]  인 경우

4인 트럭은 2초된것으로 다음 차례에서는 already로 들어갈 것이고, 5인 트럭은 1초된것으로 1초가 더 지나야 완전히 지나갈 것이다.

time이 bridge_length가 되는 것을 기준으로 다리를 다 지나간 것을 체크하고, 다름 트럭을 본다.

 

 

    • 코드
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
def solution(bridge_length, weight, truck_weights):
    count = len(truck_weights)
    answer = 0
    already = [] #지나간 트럭
    ing = [] #지나가고 있는 트럭
    time = [] #ing의 트럭의 시간
    totalweight = 0 # sum을 없애서 시간을 낮추기 위함
 
 
    while len(already) != count:
        num = True
        while len(truck_weights) >= 1 and totalweight + truck_weights[0<= weight:
            totalweight += truck_weights[0]
            ing.append(truck_weights.pop(0))
            time.append(0)
            num = False
            for i in range(len(time)):
                time[i] += 1
            if time[0== bridge_length: #시간 계산
                time.pop(0)
                totalweight -= ing[0]
                already.append(ing.pop(0))
            answer += 1
        if num: #위에서 append 된 경우는, 시간계산 이미했으므로 False인 경우는 할 필요 없음
            for i in range(len(time)):
                time[i] += 1
            answer += 1
        if time[0== bridge_length:
            time.pop(0)
            totalweight -= ing[0]
            already.append(ing.pop(0))
 
 
    answer += 1
    return answer
cs

 

  • 문제 :

fruits = ['apple','grape','strawberry','banana'] 4개의 과일이 있다

내가 가지고 있는 과일 리스트에서 각각의 과일들이 몇개 있는지 알아보고,

가장 많은 과일들을 순서대로 알아보자.

같은 수의 과일이라면 과일명을 기준으로 내림차순으로 나타내어라

fruits중 내가 가지고 있지 않은 과일은 제외하자

 

  • 내가 가지고 있는 과일 리스트

my_fuit_list = ['apple', 'grape', 'strawberry', 'strawberry', 'apple', 'apple', 'apple']

 

apple : 2개

grape : 3개

strawberry : 2개

banana: 0개

 

  • 답은

answer =  ['grape','apple','strawberry'] # 바나나는 없으므로 제외한다.

 

 

  • 코딩
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
## prerequisite
fruits = ['apple','grape','strawberry','banana']
my_fruit_list = ['apple''grape''strawberry''strawberry''grape''grape''apple']
 
## code from here
my_list = []
answer = [] # answer will be ['grape', 'strawberry', 'apple']
def solution(fruits, my_fruit_list):
    for i in range(len(fruits)):
        my_list.append([fruits[i],0])
    print(my_list) #[['apple', 0], ['grape', 0], ['strawberry', 0], ['banana', 0]]
    for i in range(len(my_fruit_list)):
        for j in range(len(fruits)):
            a = my_fruit_list[i]
            b = my_list[j][0]
            if a == b:
                my_list[j][1+= 1
                break
    print(my_list) # [['apple', 2], ['grape', 3], ['strawberry', 2], ['banana', 0]] / not yet sorted
    my_list.sort(key=lambda x:(x[1], x[0]), reverse=True)
    # my_list.sort(key=lambda x:(-x[1], -x[0]))
    ## checkpoint : 1. '-' means reverse 2. first sort by x[1](count) and then if there is same value, sort by x[0](name)
    print(my_list) # [['grape', 3], ['strawberry', 2], ['apple', 2], ['banana', 0]]
 
    for fruit, i in my_list:
        if i != 0# except for no fruit
            answer.append(fruit)
    print(answer)
    return answer
 
print('answer is ',solution(fruits,my_fruit_list))
 
cs

 

  • 정렬방법

2차원 배열을 정렬할 경우 key를 사용하여 정렬한다.

내림차순일 경우, reverse = True를 붙이거나 '-'부호를 붙인다.

 

my_list.sort(key=lambda x:(x[1], x[0]), reverse=True)

or

my_list.sort(key=lambda x:(-x[1], -x[0]))

 

 

  • example

my_list = [['apple', 2], ['grape', 3], ['strawberry', 2], ['banana', 0]]

| |

my_list.sort(key=lambda x:(x[1]x[0])reverse=True)

| |

my_list = [['grape', 3], ['strawberry', 2], ['apple', 2], ['banana', 0]]

 

# x[1]인 숫자대로 내림차순 후에, strawberry와 apple의 x[1]이 같기 때문에

# x[0]인 과일의 이름으로 내림차순을 한 결과이다.

 

nodejs를 처음 접했을때,

당연히 새로운 것은

>>> 비동기.. 처리..? 였다. <<<

 

사실 왜이렇게 어려운 말을 쓰는지 모르겠는데,

그냥 위에서부터 한줄 한줄 처리하는 것이 아니라,

빨리 처리되는 것부터 처리하겠다는 것이다.

그러다보니, 서로 연결되어 있는 함수일 때,

error가 발생하게 되고.

내가 원하는 순서대로 처리되지 않는다는 문제가 발생하게 된다.

 

이럴때 쓰는 것이 callback 함수가 되는 것이다.

그런데, callback이 직관적으로 보이지 않으니 나타난 것이,

Promise가 생기게 된 것이고, 

더 나아가,

promise를 사용하는, async await 가 나타나게 된 것이다.

 

즉,

nodejs는 비동기 방식 

callback 함수 필요

promise 개념발생

aysnc await를 활용한 파이썬과 같이 위에서부터 처리하는 듯한 표현방식 출연

 

이 된 것이다.

 

진짜 이해안갔는데, 이제서야 이해됨..

 

 

1. 기본적인 함수 표현방식

같은 함수를 두가지 방식으로 적어봤다.

함수 두개는 같은 함수이다.

1
2
3
4
5
6
7
8
9
10
11
name = function(){
    var data = 100
    return data
    }
 
fucntion name(){
    var data = 100
    return data
    }
 
name()
cs

 

2. async await 표현방식

1
2
3
4
5
async function name(){
    let data = await 프로미스 객체를 반환하는 메서드명()
    console.log(data)
    return data
    }
cs

await를 사용하려면 function앞에 async를 붙여야 한다.

그냥 쉽게 생각하면 사실, console.log(data)에서 undefined가 출력될 수가 있는데,

그 위에 await를 통해,

변수 data가 모두 담아질 때까지 await(기다리고),

그 다음줄이 실행되는 것이다.

이러면 undefined로 출력되지 않고 내가 원하는 data가 출력될 것이다.

 

두번째로, await뒤에는 promise 객체를 반환하는 매서드명이 들어가야한다.

 

3. Promise 객체?

 

Promise객체를 반환하면, callback함수를 복잡하게 쓸필요가 없고,

좀 더, 직관적으로

형식 :    Promise객체.then().catch()  

promise객체를 통해 나온 데이터를 가지고,

resolve일 경우에는(에러없이 promise 실행완료),

그다음 함수는 then이 실행되고,

 

reject(promise가 제대로 실행안됨)일 경우에는,

error이므로 catch가 실행된다.

마치, try() catch() 같음..

 

axios로 예를 들어보겟다.

 

axios.get(url)

을 하면 해당 url에 get요청을 해서 반환되는 JSON과 같은 Object가 반환된다.

axios는 Promise 객체를 반환한다.

axios.get(url).then(function(response){ console.log(response) }.catch(function(err){ console.log(err) }

axios.get(url)
>>> axios 실행 : promise 객체를 반환하는 함수 

.then(function(response){ console.log(response) }
>>성공시(resolve시,) 반환된 객체를 response에 담고, 데이터 반환하는 함수

.catch(function(err){ console.log(err) }  
>> 실패시(reject시,) err출력

 

4. 결론 - axios를 활용해서 async await 함수를 만들어보자

1
2
3
4
5
6
7
8
9
10
use = async function(){
    let response;
    let data = await axios.get('url'// axios는 promise를 반환하는 메서드임(api get호출)
    data.then(function(res){     // promise객체는 .then().catch() 와 같이 직관적으로 다음함수 실행 가능
        response = JSON.stringify(res)
    })
    return response
}
 
console.log(use())
cs

이렇게 쓰면 되겠네요!!

promise와 aync await를 모두 활용하였습니다..

 

 

string.find(x) = x의 위치

반환값 : 그 문자의 위치반환, 만약 그 문자가 존재 하지 않으면 -1반환

활용 : 어떤 문자열 old = "stringstring"에서 중복되는 값들을 제외하고 싶다면, 빈 문자열 new= ""를 하나 만들어준 후, for를 돌려서 new에 old[i]를 find하여 이 값이 -1이 아니면 추가하고 -1이면 넘어가는 식으로 로직을 세운다.

 

string.find(x) = x의 위치

string[::-1] = 문자열을 거꾸로 뒤집기

list.sort(reverse = True) : 내림차순 False : 오름차순(기본값)

sorted(list)

 

list.index(x) = x의 위치

list.remove(x) = list에서 x와 같은 값 제거

- 첫번째 x만 제거 됨, 여러번 제거하고 싶은 x의 개수만큼 반복하기

list.reverse() = list를 거꾸로 뒤집기

list.pop(x) = list에서 x만 뽑아냄/ 동시에 list에서 x제거 

 

for문

*) 2중, 3중, 4중 이상의 for문을 돌릴때, 고정시키고 싶은 것들 부터 for문을 돌리고 가장 안쪽이 고정시키지 않고 계속 돌릴 것으로 한다.

 

*) 즉, 보통 가장 바깥쪽 for문의 개수가 가장 적게된다.

 

aList = [1,2,3]

bList = [4,5,6]

1.더할때

aList + bList = [1,2,3,4,5,6] 

list끼리 더하면 한 리스트로 더해진다

2. append할때

aList.append(bList) = [1,2,3,[4,5,6]]

이렇게 된다.

 

 

 

 

0. 참고하면 좋은 사이트


- 넷매니아.com

 

1. 라우팅 프로토콜의 neighbor 조건

1) ospf
- Hello & Dead interval
- Area번호
- MTU사이즈
- 인증방식

2) eigrp
- process ID
- 같은 k상수, 가중치
- 인증방식

*)추가사항
. BGP라우팅 프로토콜은 UDP방식의 네이버를 확인하지않고 TCP방식을 사용한다.
. Ospf, eigrp - UDP, multicast
. BGP - TCP, unicast

2. GRE터널

. next-hopd으로 광고해야하고 interface로 광고하면 안된다.

3. L4의 deep dive

1) 같은 네트워크의 서버끼리 통신하는 경우


- L4의 vip로 통신하는 경우

: ping을 때려도 drop되어 통신안됨. response를 받지 못함

 

-> (mac table - real mac : port num)가

L2 or L3에 저장이 되어 맥통신이 되면서

reponse를 받을때 서버에서 요청한 vip가 아니라

real mac으로 response를 받으면서,

내가 요청한 destination ip가 아니라

real ip로 response가 오면서

그 패킷을 drop하게 되는 것이다.

- 진짜 real ip 로 통신하는 경우

: 통신 잘됨 ping 때렸을 떄 응답 잘 됨.


-> real ip로 요청했기 때문에

mac table에 잘 저장이 되면서,

내가 요청한 destination ip를 가진 서버에서

그대로 source ip로 reponse가 오기때문에

 통신이 잘된다.

1-1) 결론

내부 서버끼리 통신할 때에는 SNAT가 필수적이다. 

: vip > vip

 

2) DSR구조의 장/단점

2-1) 장점
1. Loop free
2. Port flexible
3. Performance 2배

2-2) 단점
1. 구성 복잡
2. Log가 다 안보임 -> input에 대한 log만 보인다.

 

2) DSR에서 세팅

- 서버 : DSR의 vip와 같은 ip로 loopback(/32)을 구성하여 패킷을 보낼때 source ip를 이 loopback이 될 수 있게 설정해야한다.

 

 

4. ARP table 의 원리

1) arp table에 채워지는 기준

 

- mac table처럼 무조건 그 장비를 지나갈 때마다 source mac을 learning하는 것이 아니다.

(이 부분 착각하는 사람들이 많음)


- 내가 packet을 보낼때, ip 만 알고 mac을 모를 때 보내는 것이 arp broadcast 패킷

 

-> 즉, 이를 위해 arp broadcast 패킷을 보내는

그 주체의 arp table이 채워지는 것이다.


이 과정에서 L2스위치를 지나가고

(당연히 L2에서는 arp table이 없지만),

 L3도 지나가면서 broadcast가 전달이 되지만

그건 중요하지않다.


Broadcast를 보낸 end-point가 그 response를 받았을 때, 자신의 arp table에 저장이 되는 것이다.

2) vlan으로 네트워크가 나눠져 있다면

(즉 L3를 넘어 다른 네트워크와 통신할때도 포함된다)

 

.구성도

< L3 - (Gi0/0)L2 - (Gi0/1)host A, (Gi0/2)host B > (interface는 L2 기준)
Vlan 100 : host A
Vlan 200 : host B


<A -> B로 통신하는 경우>
a) A의 arp table mapping 정보
.L3 g/w의 ip : L3의 mac

(라우팅 테이블을 보고 같은 네트워크가 아니기 때문에 G/W로 먼저 패킷을 보낼 것이므로 G/W에 대한 mac을 배운후 패킷을 보내는 것이다.)

b) L2의 mac table mapping 정보
.A mac : Gi0/1(requesst할때)
.L3 g/w mac : Gi0/0(reponse할때)

c)L3의 arp table mapping 정보
.B ip : B mac

(broadcast 를 요청할 후 받았을 때 채워짐)

3) 하나의 vlan으로만 이루어져 있다면
.구성도

< L3 - (Gi0/0)L2 - (Gi0/1)host A, (Gi0/2)host B > (interface는 L2 기준)
Vlan 100 : host A, host B(Vlan 없어도 됨)


<A -> B로 통신하는 경우>
a) A의 arp table mapping 정보
.B ip : B mac

b) L2의 mac table mapping 정보
.A mac : Gi0/1(requesst할때)
.B mac : Gi0/2(reponse할때)

c) L3의 arp table mapping 정보
.아무것도 없음

5. VLAN 통신의 원리(tagged & untagged)

- 스위치에 들어올때

1) Port가 tagged(trunk)인 경우

tagged되서 들어오면(native vlan이 아니라, 일반적인 경우)
Tagged된 vlan과 같은 vlan으로 설정된 access port로만 나갈 수 있다.

2) Port가 untagged(access or native vlan)인 경우

Vlan을 모르는 상태이니, 무조건 들어올 수는 있지만,
그 포트에 설정된 vlan으로 스위치 내부에서 인식하기 때문에
그 포트에 설정된 vlan과 같게 설정된 port로만 나갈 수 있다

즉, trunk로 설정된 포트로 들어왔는데 untagged상태인 native vlan이라면
설정된 native vlan과 같은 vlan으로 설정된 access port로만 나갈 수 있다.

- 스위치에서 나갈때

Trunk port라면 tagged되서 나가고(native vlan 제외)
Access port라면 untagged되서 나간다.

결론)
스위치에 들어올땐 자유지만,

스위치 내부에서는 같은 vlan으로 설정된 포트끼리만 이동가능하며,
스위치에서 나갈 때는 trunk라면 tagged되서 나가며,
Access port라면 untagged되서 나간다.

 

6. 통신시, Mac address & IP address의 변화

- source mac, destination mac
: LAN segment가 바뀔때마다 변한다

- IP
: 절대 안변함
변한다고 느끼는 이유는 아마도 ARP때문일 것
but arp 패킷으로 mac을 알아내는 것 뿐이고,
통신할 때에는 IP바뀌지 않는다.

7. STP block port선정 방법

 

0) 먼저, Root스위치 선정 후, 루트스위치 기준으로 계산한다.
1) cost값(higher)
2) sender BID값 (higher)
    BID = vlan + priority + mac
3) sender port num값(higher)

 

8. 무선

8-1) 무선의 속도 개선방법
1. 안테나를 늘린다.
2. 채널본딩을 한다.
3. 변조방식을 개선한다.

8-2) 무선의 품질을 개선하는 방법(SNR비율을 높이는 방법)
1. Power를 높인다.
2. 안테나 방식 : MU-MIMO가 SU-MIMO보다 좋다.
3. beamforming방식 사용한다.
-> 특정 단말에게 신호를 집중적으로 보낸다(움직이지 않는 공간일 때 특히 좋다)
4. 기존 주파수와 곂치지 않게ㅔ 채널을 분배한다.
5. 지향성 안테나를 사용한다.

9. SDWAN
: control plane과 data plane의 분리

장점
- loop free하다
- capacity 부족문제 해결
- 수평적 중심의 통신
- 인프라 확장 시 필요 장비만 추가
- 신궈 Leaf장비 자동 인식
- 서비스 영역별 분리 작업

 

10. 통신이 되지 않는 이유

 

1) L2에서 L3바깥으로 패킷이 나가지 않을 때

- 그 장비의 default gateway를 세팅하지 않은 것이다.

- 이 상황에서는 L2내부에서는 통신이 잘 된다.

+ Recent posts