# 리스트 자료형 
# 여러 개의 데이터를 연속적으로 담아 처리하기 위해 사용하는 자료형 
# 자바에서의 배열의 기능 및 연결 리스트와 유사한 기능

# 리스트 초기화
# 대괄호[] 안에 원소를 넣어 초기화
# 각 원소는 쉼표, 로 구분
# 비어 있는 리스트를 선언할 때 -> list() 혹은  []
# 리스트의 원소에 접근할 때는 인덱스 값을 괄호에 넣음
# 인덱스는 0부터 시작



# 직접 데이터를 넣어 초기화
a = [1, 2, 3, 4, 5]
print(a)

# 리스트의 세 번째 원소 출력
print(a[2])

# 크기가 n이고, 모든 값이 0인 1차원 리스트 초기화
n = 10
a = [0] * n
print(a)



#test 
#[1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
a = [1,2] * 5
print(a)

a[7] = 5
print(a)






# 리스트의 인덱싱과 슬라이싱

# 인덱싱
# 인덱스 값을 입력하여 리스트의 특정한 원소에 접근하는 것.
# 파이썬의 인덱스 값은 양의 정수와 음의 정수를 모두 사용할 수 있음.
# 음의 정수를 넣으면 원소를 뒤에서부터 거꾸로 탐색하게 됨
# 앞에서부터는 인덱스가 0으로 시작, 뒤에서부터는 -1로 시작

a = [1, 2 , 3 , 4 , 5, 6, 7, 8, 9]

# 8번 째 원소만 출력
# 8
print(a[7])

# 뒤에서 첫 번째 원소 출력
# 9
print(a[-1])

#뒤에서 세 번째 원소 출력
# 7
print(a[-3])

# 네 번째 원소 값 변경
# [1, 2 , 3 , 0 , 5, 6, 7, 8, 9]
a[3] = 0
print(a)




# 슬라이싱
# 리스트에서 연속적인 위치를 갖는 원소들을 가져와야 할 때 사용
# 대괄호 안에 콜론: 을 넣어서 시작 인덱스와 끝 인덱스를 설정할 수 있음
# 끝 인덱스는 실제 인덱스보다 1을 더 크게 설정 !

a = [1, 2 , 3 , 4 , 5, 6, 7, 8, 9]

# 네 번째 원소만 출력
# 4
print(a[3])

# 두 번째 원소부터 네 번째 원소까지
# [2, 3, 4]
print(a[1:4])


# test
# 5번째 원소부터 끝까지
# [5, 6, 7, 8, 9]
print(a[4:9])
# ->인덱스 4 부터 인덱스 9보다 작은 원소까지 가져오는 것
# 4 <= a < 9



# 리스트 컴프리헨션
# 리스트를 초기화하는 방법 중 하나
# 대괄호 안에 조건문과 반복문을 적용하여 리스트를 초기화할 수 있음

# 0부터 9까지의 수를 포함하는 리스트
array = [i for i in range(5)]
# range함수는 0 ~ 4까지의 값을 차례로 i가 수려할 수 있도록 해주는데, 
# 그때 그 값(i)을 원소로 설정해서 리스트로 만들어라
# 결과: [0, 1, 2, 3, 4]
print(array)
# 작성할 때 반복문부터 넣는 것이 좋음


# test
# [0, -1, -2, -3, -4,- 5, -6, -7, -8, -9]
a = [ i*-1 for i in range(10)]
print(a)

# [1, 3, 5, 7, 9]
a = [2*i+1 for i in range(5)]
print(a)

# 0부터 19까지의 수 중에서 홀수만 포함하는 리스트
# [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
a = [i for i in range(20) if i % 2 == 1]
print(a)

# 1부터 9까지의 수들의 제곱 값을 포함하는 리스트
# [1, 4, 9, 16, 25, 36, 49, 64,81]
a = [i*i for i in range(1,10)]
print(a)




# 리스트 컴프리헨션과 일반 코드 비교
# 0부터 9까지의 수 중 홀수만 포함하는 리스트

# 방법1: 리스트 컴프리헨션
array = [i for i in range(10) if i % 2 == 1]
print(array)

# 방법2: 일반적인 반복문, 조건문 사용
array = []
for i in range(10):
  if i % 2 == 1:
    array.append(i)

print(array)


# 리스트 컴프리헨션은 2차원 리스트를 초기화할 때 효과적으로 사용됨.
# 특히, N x M 크기의 2차원 리스트를 한 번에 초기화 해야 할때 매우 유용.
# 좋은 예시: array = [[0]*m for_in range(n)] 
# 나쁜 예시: array = [[0]*m] * n 

# 2 * 3 크기의 2차원 리스트로

# 좋은 예시
# [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
n = 3
m = 3
array = [[0] * m for _ in range(n)] 
print(array)

# 나쁜 예시
# [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
array = [[0]*m] * n
print(array)

# 좋은 예시와 나쁜 예시의 결과가 같은 것 처럼 보일 수 있지만,
# 나쁜 예시의 경우 생성된 내부 개체들이 모두 같은 객체로 인식되기 때문에
# 특정 인덱스의 값만을 변경해야 할때, 
# 같다고 인식된 객체의 인덱스의 값까지 모두 변경되는 문제가 발생하게 됨.

# 즉, array[1][1] = 5 라고 할 경우,
# 좋은 예시의 경우는 [[0, 0, 0], [0, 1, 0], [0, 0, 0]]
# 나쁜 예시의 경우는 [[0, 1, 0], [0, 1, 0], [0, 1, 0]] -> 모두 같은 객체로 인식되기 때문



# 언더바
# 파이썬에서는 반복을 수행하되 반복을 위한 변수의 값을 무시하고자 할 때 언더바_를 자주 사용
# 변수 필요없이 그냥 반복만 하고 싶을 때 사용

# 1부터 9까지의 자연수를 더하기(변수 필요)
summary = 0
for i in range(1, 10):
  summary += i
print(summary)

# "Hello World"를 5번 출력하기(변수 필요 없음-> 언더바 사용)
for _ in range(5):
  print("Hello World")


