프로그래머스 level 0 정리

kiki·2024년 1월 27일
0

기본기

목록 보기
3/9

range의 범위 설정

  • range(2,n+1,2)로 짝수만 구할 수 있다.
  • range는 iterable한 객체를 반환하므로 sum에 바로 넣을 수 있다.
  • range는 iterable한 객체를 반환하기에, list로 보고싶다면 list()로 감싸줘야한다.

list 거꾸로

  • list.reverse()하면 반환 값 없이 list를 뒤집는다.
    • string엔 적용되지 않는 함수이다.
  • list[::-1]와 같이 슬라이싱에서 증가량을 이용한 방법이 있다.
    • 문자열도 동일하게 string[::-1]과 같이 뒤집을 수 있음.

실행 속도

  • map > list comprehension > map + lambda > for loop
  • list comprehension보다 map을 쓰는 걸 습관들여야겠다.

리스트 컴프리헨션

  • [i for i in list]
  • [i for i in list if i%2==0]
  • [i,j for i in list_1 for j in list_2] 이중 for문도 지원한다. 왼쪽의 for문이 먼저 실행됨
  • [i if i%2==0 else 0 for i in list] else까지 사용한다면 for문 앞에 if-else문을 적어줘야함

divmod

  • divmod(x, n)을 하면 x를 n으로 나눈 몫과 나머지를 한 번에 반환한다. 하지만 작은 수에서는 divmod가 x//n, x%n을 따로 하는 것보다 시간이 더 걸린다 하니 큰 수에서 사용하는 것이 좋겠다.

리스트 내 자신보다 큰 값의 갯수

  • reverse sort 후 자신의 index가 자신보다 큰 값의 갯수이다! 참고 문제
  • 아니면 comprehension으로도 작성할 수 있다 sum(1 for i in list if i>height)

금액 별 할인율

  • dictionary와 for문을 이용하자! 관련 문제
  • dictionary에 값과 (1-할인율)을 저장해두고 이를 for문을 돌며 값과 비교한다.

특정 값 count

  • list 내에서 특정 값이 몇 개인지 알기 위해선 count 함수를 쓰면 된다. list.count(x)
  • 만약 list 내 모든 값의 갯수가 필요하다면 collections의 Counter를 사용할 수도 있다. Coutner는 dictionary를 반환한다.

float 소수점 관리

  • round를 통해 반올림이 가능(사사오입)
  • int를 이용해 버림이 가능
  • math 패키지 사용 (모두 int 반환)
    • ceil은 그냥 올림
    • floor는 내림
    • trunc는 버림

comprehension 대신 int

  • 1 if n%2==0 else 0와 같이 작성해왔는데, 그러지 말고 int(n%2==0)으로 쓰면 더 간단하다. 가독성은 모르겠지만...
  • ==, != 연산으로 bool type을 반환하기 때문에 int를 쓰면 True일 경우 1, False일 경우 0이 반환된다.

비트 시프트

  • n << t n에 2**t를 곱한 값을 의미한다.
  • n >> tn을 2**t로 나눈 값을 의미한다.

컴퓨터엔 값이 2진수로 저장되기 때문에 <<, >> 연산자로 비트를 밀어주거나 당겨주면 값이 2배씩 늘어나거나 1/2씩 줄어든다.

range의 반환 타입

  • range는 range class를 반환하니 list로 덧씌워야한다.
  • list(range(1,n,2))

set

  • set(문자열)은 문자열의 각 요소가 원소로 구성된 집합을 반환한다. (중복 제거)
  • s1&s2는 s1과 s2의 교집합을 의미한다. (intersection 함수)
  • s1|s2는 s1과 s2의 합집합을 의미한다. (union 함수)
  • s1-s2는 s1과 s2의 차집합을 의미한다. (difference 함수)

is_integer()

is_integer()은 x.is_integer()와 같이 사용하고 이는 타입 확인이 아닌 형태 확인이다.
즉 x가 3.0, 즉 float여도 True를 반환한다.

약수

  • 약수는 range(1, n//2+1)의 범위에서 나눠지는지 확인하면 좀 더 빠르게 확인할 수 있다. (약수에 본인 n을 포함하는 것 잊지말기!)

문자열 특정 문자들 제거

  • ''.join([i for i in str if i not in 'aeiou'])
  • 이렇게 하면 a,e,i,o,u 문자들을 제거한 새로운 문자열이 반환된다.
  • in 문자열이 가능하다는 걸 알고있자.

isdigit()

  • 문자열이 숫자(정수, 지수)만으로 이루어져있는지 확인하는 함수

대문자, 소문자

  • lower(): 소문자로 변환
  • upper(): 대문자로 변환
  • islower(): 소문자인지 확인
  • isuppper(): 대문자인지 확인
  • swapcase(): 대문자는 소문자로, 소문자는 대문자로 변환

set sort

  • set의 특징은 두가지 1) 중복을 허용하지 않는다. 2) 순서가 없다.
    • 그래서 인덱싱이 불가하다.
  • 근데 왜 sorted는 될까? sort는 그 자체를 정렬하지만 sorted는 넘겨진 인자의 목록을 정렬해 정렬된 리스트를 반환하기 때문이다.
  • 그렇기 때문에 sorted(set)은 가능하지만 set.sort()는 불가능하다.

sorted

  • 위에서 말했듯이 sorted는 인자의 요소들을 정렬해 list로 반환한다.
  • 문자열에도 sorted를 사용할 수 있는데, 정렬 후 string type으로 받고싶다면 sorted 후 join해줘야한다.
    • ''.join(sorted(str))

특정 문자의 인덱스 찾기

  • list, tuple, string에서는 list.index(x)

  • string에서는 str.find(x)와 같이 find로도 사용할 수 있다.

    • 앞에서부터 x를 찾아, 가장 먼저 나오는 x의 인덱스를 반환한다.
    • 만약 문자열의 경우, 뒤에서부터 찾고싶다면, rindex, rfind를 사용하면 된다. (리스트 등은 안됨)
  • 차이점

    • find는 찾을 수 없을 경우 -1을 반환하지만, index는 에러를 일으킨다

str to list

  • list(str)은 str의 모든 문자를 각각의 원소로 갖는 리스트로 변환된다. (공백 포함)
    • "We are the world"
    • ['W', 'e', ' ', 'a', 'r', 'e', ' ', 't', 'h', 'e', ' ', 'w', 'o', 'r', 'l', 'd']

중복 문자 제거하는 방법

result = ""
    for i in my_string:
        if i not in result:
            result+=i
    return result

map

리스트에 함수를 일괄 적용하는 방법

l = [1,2,3,4,5]
list(map(int, l)) => ['1','2','3','4','5']

하지만 map은 iterator 객체를 반환하니 list로 감싸서 반환해야한다.

map도 comprehension도

  • map도, comprehension도 iterator 객체를 반환한다. 그렇기 때문에 map, comprehension 후 list로 반환받기 위해선 list로 감싸줘야하며, 만약 sum()과 같은 함수를 사용한다면 list로 감싸주지 않아도 된다.
  • generator는 iterator다.. 참고

factorial

from math import factorial
factorial(n)

combination

from math import comb
comb(m,n)
m개 중 n개 뽑는 경우의 수! => 조합. math 패키지에 있다.

최대 공약수 (gcd)

from math import gcd

greatest_common_divisor = gcd(a,b)

중복 모두 제거

  • 리스트에서 중복되는 요소를 하나만 남겨두는 거 말고!! 중복되는 값이 있다면 모두 제거하기 위해선 count나 Counter를 사용할 수 있다.
from collections import Counter

x = [1,1,2,3,3,6,8,9,9]

### 1) 
[i for i in x if x.count(i)==1]

### 2)
[i for i in set(x) if x.count(i)==1]

### 3)
counts = Counter(x)
[i for i,j in counts.items() if j==1]

split

  • split 함수는 string 함수를 인자 기준으로 분리해 각 원소로 만들어 리스트를 반환한다.
  • 인자를 전달하지 않고 str.split()와같이 사용한다면 공백(몇개든 상관없이) 기준으로 분리된다. 만약 str이 3 23 567이면 [3,23,567]이 반환된다.
  • 참고문제

sort

array.sort(key=lambda x: (abs(n-x), x))

  • sort 시 정렬할 key 값을 lambda로 지정해주는 방법! 근데 여기서 정렬 key를 두 개도 넣어줄 수 있다. 이러면 abs(n-x)로 먼저 정렬하고 같은 경우엔 x로 정렬하는 것이다.
  • 참고 문제
sorted(numlist, key = lambda x: (abs(n-x), -x))

참고 문제
이렇게 하면 numlist란 리스트를 abs(n-x)로 1차 정렬하고 x값을 기준으로 내림차순 정렬한다.
정렬 조건(?)이 두개 이상이라면 꼭 괄호로 묶어주는 거 잊지말기..!

list to str

  • [1,2,5]의 list를 고대로 문자열로 만들고싶다면 str(list) 하면 끝..! 그러면 "[1,2,5]" 가 되므로 이대로 사용하면 된다...
  • 아니 근데 쓰고보니까 그냥 그 문제에서만 사용할 것 같은 방법이네

만약 리스트의 값들을 모두 하나의 문자열로 합치고싶다면, join을 사용하면 될듯하다. 만약 리스트의 원소들이 str이 아니라면 map도 같이 써줘야겠지.

''.join(map(str, list))

이진수, 십진수 변환

  • 이진수 to 십진수: int(binary_value, 2) (이때 binary_value는 str)
  • 십진수 to 이진수: bin(decimal) (이때 decimal은 int)
    • bin의 반환 타입은 str이며 0b1010와 같은식. 그렇기 때문에 우리가 직접 이진수를 다루기 위해선 bin(decimal)[2:]와같이 사용

소인수분해

def solution(n):
    d = 2
    answer = set()
    while d<=n**0.5:
        if n%d!=0:
            d+=1
        else:
            answer.add(d)
            n = n//d
    if n>1:
        answer.add(n)
    return sorted(answer)

여기서 효율성을 높이기 위해서 n**0.5보다 작거나 같은 값을 기준으로 뒀다.
그랬기때문에 마지막에 n>1일때 n도 소인수분해 값에 넣어줘야한다.

이건 거의 공식처럼 외우고있어야겠다.

리스트 슬라이싱

슬라이싱의 경우 범위를 초과해도 에러가 나지 않는다.
a = [1,5,3,6,2]이 있을 때, a[3:6]해도 에러없이 [6,2]가 출력될 뿐이다.
그러니까 인덱스 3에서 끝까지의 값을 가져오기 위해 a[3:5]로 슬라이싱해도 에러가 나지 않는것이다.

리스트 인덱싱

def solution(numbers, k):
    return numbers[2 * (k - 1) % len(numbers)]

이 문제를 풀면서 깨달?은건데...
해당 문제에서 1명을 건너뛰고 공을 던지니 2를 곱해주고
인덱스 0부터 공을 던지기 때문에 k-1을 해주고
%len(list)를 이용해서 리스트의 인덱스를 넘는 값을 처리해준다.

이렇게 간단하게 처리가 가능하다니!
인덱싱에 대해서 좀 더 공부할 필요가 있겠다.

min, max

min, max로 좌표를 벗어나지 않도록 조절해줄 수 있다. 해당 문제에서 아주 유용하게 사용된다.

def solution(keyinput, board):
    result = [0,0]
    max_x, max_y = board[0]//2, board[1]//2
    for key in keyinput:
        if key=='left':
            result[0] = max(result[0]-1, -max_x)
        elif key=='right':
            result[0] = min(result[0]+1, max_x)
        elif key=='up':
            result[1] = min(result[1]+1, max_y)
        else:
            result[1] = max(result[1]-1, -max_y)
    return result

이 문제도 좌표를 이용하는 문제인데, 여기 적용할 수 있지 않을까 싶다.

2차원 리스트 flatten

l = [[1,2],[2,3],[3,4]]
sum(l, [])

이렇게 하면, []+[1,2]+[2,3]+[3,4]와 같은 연산이 일어나기때문에 1차원 리스트로 만들 수 있다.

:= (바다코끼리) 할당과 반환을 동시에!

변수 := 표현식과 같이 사용해 가독성을 올리고 코드를 짧게 해주는 장점이 있다네..

dictionary get

dictionary에서 값을 가져올 때 인덱싱도 되지만 get을 사용하는 방법도 있다.
만약 가져오려하는 값의 key가 dictionary에 없다면 error가 나기 때문에 get을 이용하면 한 줄로 간단하게 처리할 수 있다.

dict.get(x, -1)

만약 dict.get(x)로 지정하고 dict에 x가 없다면 이는 None(NoneType)을 반환한다.

바다코끼리와 get을 이용해 간단하게 해결하기

def solution(id_pw, db):
    if db_pw := dict(db).get(id_pw[0]):
        return 'login' if db_pw==id_pw[1] else 'wrong pw'
    return 'fail'

이 문제에서 배운게 많다!
1) 이차원 리스트를 dict()함수를 사용해 dictionary로 변환할 수 있다.
2) get을 사용해 예외를 처리할 수 있다.
3) :=를 이용해 할당과 반환을 동시에 할 수 있다.

값의 소인수가 특정 값으로만 이루어져있는지 확인

그냥 특정 값으로 냅다 계속 나눠버리면 된다.
그러고 최종 몫이 1인지 확인

while b%2==0:
    b = b//2
while b%5==0:
    b = b//5
return 1 if b==1 else 2

이 코드는 b의 소인수가 2나 5로만 이루어져있는지 확인하는 코드이다.
해당 문제에서 사용된다.

리스트를 할당

a, b = list[:2]
이렇게 하면 list[:2]의 두 원소가 각각 a,b로 할당된다.

리스트 슬라이싱

list[::2], list[1::2] -> 이와 같이 홀수번째 수, 짝수번째 수 만을 뽑아낼 수 있다.

등차수열의 합..

(n*(2n+(n-1)d))//2
d는 공차, n은 마지막 항

strip 함수

특정 문자, 문자열, 공백을 제거해주는 함수이다.
lstrip은 왼쪽, rstrip은 오른쪽, strip은 양쪽
ex) string.lstrip('a') -> 왼쪽에 나타나는 a들을 제거해준다.

주의) 만약 인자를 'ab' 처럼 문자열로 넘겨준다면, a와 b의 모든 조합을 제거해준다. 즉 a가 나타나도, b가 나타나도, ab 혹은 ba가 나타나도 제거해준다.

문자열 formating

  • f'{a}+{b}는 {a+b}입니다'와 같이 f'{}~{}' 형식으로 포맷팅 가능하다.

에러 처리

try except문으로 처리할 수 있다. 즉 try구문에서 에러가 발생하면 except문을 실행하는 것

try:
	~~
 except:
 	~~

리스트 연산시 주의 (참조)

[[0]*n]*n 하면 이중 리스트가 만들어지지만, 여기서 하나의 값을 변경해보면 이상한 점을 알 수 있다.
바로 모든 행이 하나의 리스트를 참조한다는 것. 즉 [0]*n은 n개의 0으로 이루어진 리스트(독립적인 메모리에 위치한 각 원소들)를 반환하지만, [[]~]*n에서 문제가 발생하는 것.

그러니 아래와 같이 for문을 사용해 이중 리스트를 만들어주는 게 좋다.
[[0]*n for _ in range(n)]

  • 리스트 복사할 때, copy함수를 사용하자!

리스트 간 연산

  • 부등호
    • a<b와 같이 부등호 연산을 하면, a와 b에서 처음으로 다른 두 값에 대한 부등호 연산이 결과로 나온다.
    • 주의해야할 것은, 두 리스트 길이가 다른 경우 짧은 리스트는 작은 값으로 간주됨

startswith, endswith

접두사, 접미사를 확인할 수 있는 함수이다.
ex) str.startswith('~~')

dictionary

  • values(), keys(), items()와 같은 함수들을 사용할 수 있음
    • values, keys의 경우 반환값이 리스트 형태가 아니기에, 리스트 형태로 변환하고싶다면 list() 함수로 감싸주면 된다.

값이 없는 객체는 false

''[] 등 값이 없는 객체는 false로 인식되기 때문에, 이를 조건문에 잘 쓰면 코드가 간단해진다!

리스트 원소 할당

list_3가 3개의 원소를 가진 리스트일때, a,b,c = list_3와 같이 각 값에 할당 가능하다.

아스키코드

ord()는 문자를 아스키코드로 변환해주고,
chr()는 아스키코드를 문자로 변환해준다.

*참고: 'A'는 65부터 시작, 'a'는 97부터 시작한다.

필요없는 코드 실행 막기

def solution(arr, k):
    distinct = []
    for item in arr:
        if item not in distinct:
            distinct.append(item)
        if len(distinct)==k:
            break
    return distinct+[-1]*(k-len(distinct))

이 문제를 푸는데, 리스트 내에서 고유한 숫자를 뽑아내는 부분에서 필요 없는 코드 실행을 막을 필요를 느꼈다!
이 코드에서는 if len(distinct)==k: break 부분인데, 문제에서 필요한 distinct 원소는 최대 k개이기 때문에, distinct의 길이가 k가 됐을 때 break로 for문을 빠져나왔다. 이렇게 하면 불필요한 코드 실행을 줄일 수 있다!

반환 방법

return result or [-1]과 같이 반환하려는 result 리스트가 빈 리스트일 때 대신 반환할 값을 지정할 수 있다.
우리가 if문에서 if A or B와 같이 쓰면 A나 B가 True일 때 조건문이 실행되지 않는가?
즉 A가 True면 (A or B)에서 A가 반환되어 조건문이 실행되는 것이다.
그렇기 때문에 return 구문에서도 True(빈 리스트가 아닌 것)인 리스트가 반환되는 것이다. 우리는 result가 빈 리스트인지 아닌지 확인해야하므로, result를 [-1] 앞에 적어주면 된다.

0개의 댓글