Sad Puppy 3 개발자 아지트 :: 개발자 아지트

Go언어란?

홈페이지 주소: golang.org

온라인 Go 언어 컴파일러 : play.golang.org

  • Go 언어의 역사
  • Go 언어의 특징
  • Go 언어의 쓰임새

 

Go언어는 구글에서 로버트 그리스머, 롭 파이크, 켄 톰슨이 이끌어 만들어  2009년 발표된 오픈소스 프로그래밍 언어이다. 

즉, 무료이며, 언어 발전에 기여 가능하다. 

해당 언어는 심플하며, 성능이 좋다. 

 

해당 언어는 범용 언어로, 다양한 용도로 사용되지만

특히 백엔드 서버와 시스템 개발에 적합하며, 강력한 동시성 프로그래밍을 지원함

그 이유는 성능이 좋기 때문이다. 

 

특징 요약

 

  • 클래스: 없음, 그러나 메서드를 가지는 구조체를 지원함
  • 상속: 없음
  • 메서드: 있음, 구조체는 메서드를 가질 수 있음
  • 인터페이스: 있음, 상속은 없음
  • 익명 함수: 있음, 함수 리터럴이라는 이름으로 제공함
  • 가비지 컬렉터: 있음, 고성능 가비지 컬렉터를 제공함
  • 포인터: 있음
  • 제네릭 프로그래밍: 없음
  • 네임스페이스: 없음 

 

코드 실행 과정

 

  1. 폴더 생성
  2. .go파일 생성 및 작성
  3. Go 모듈 생성
  4. 빌드
  5. 실행 

 

폴더 생성

Go 언어에서 모든 코드는 패키지 단위로 작성됨.

같은 폴더에 위치한 .go 파일은 모두 같은 패키지에 포함되며, 폴더명이 패키지명이 됨.

 

예를들어서, goproject/hi/plus

 

hi 폴더에 든 .go 파일은 hi 패키지에 속하고, plus 폴더에 든 .go파일은 plus 패키지에 속함

 

Go 코드는 .go 확장자의 파일임 

Go 모듈 생성

 

Go 1.16 버전 이후로 Go 모듈이 기본으로 적용된다. 

따라서 모든 Go 코드 빌드 전에 모듈 생성이 필요하다. 

 

이때, 모듈 생성은 아래의 명령으로 실행한다. 

$ go mod init 모듈명

# 예를 들면

$go mod init goproject/hi

 

모듈 생성시, go.mod 파일이 생성되고, 해당 파일에는 모듈명, Go 버전, 필요한 패키지 목록에 대한 정보가 담겨있다. 

 

빌드

 

$ go build

 

위 명령어를 통해 Go 코드를 기계어로 변환하여 실행 파일을 만든다. 

 

GOOS와 GOARCH 환경변수 조정을 통해 다른 운영체제 및 아키텍처에서도 호환 가능한 실행 파일 제작이 가능하다. 

(터미널에서 $ go tool dist list 명령을 통해 호환 가능한 운영체제 및 아키텍처 목록을 확인할 수 있다. )

 

 

기본 코드에 대한 구조

 

package main 
// 패키지 선언: 해당 코드가 어떤 패키지에 속하는지 알려줌 
// 패키지는 코드의 묶음이며, 여러 기능을 제공함
// Go 파일의 코드는 항상 패키지 선언으로 시작해야함
// 1번 라인은 main 패키지에 속한 코드임을 컴파일러에 알려주는 역할을 함

// main 패키지는 프로그램 시작점을 포함하는 중요한 패키지임

import "fmt"
// fmt 패키지를 가져오겠다는 의미를 가짐
// fmt는 패키지 표준 입출력을 다루는 내장 패키지임

func main(){
	fmt.Println("Hi World")
	// fmt.println()는 표준 출력으로 문자열을 출력하는 함수임.
    // 표준 출력이란 터미널 화면을 말함. 
    // Go언어 프로그램은 main()함수 부터 시작되고, main() 함수가 종료되면 프로그램이 종료됨.
}

// Go 언어에서는 외부로 노출되는 함수 앞에는 함수명으로 시작하는 주석을 달아서 함수를 설명하는 것을 
// 코딩 규약으로 권장함

/* 여러줄 

주석*/

 

 

 

 

변수

 

  • 변수 선언
  • 변수 속성
  • 타입 변환
  • 숫자 표현

 

 

변수란 값을 저장하기 위한  메모리 공간을 가리키는 것이다. 

변수는 이름, 값, 타입, 주소 속성을 가지며, 변수 간 값의 전달은 항상 복사로 일어난다. 

 

컴퓨터에서 프로그램의 코드는 메모리의 데이터를 언제 변경할지 나타낸 문서이다. 

따라서, 프로그래밍은 메모리에 있는 데이터 조작이 핵심이다. 

이를 변수를 이용하면 쉽게 할 수 있다. 

 

변수 사용을 위해 아래와 같이 선언할 수 있다. 

코드에서 변수를 선언을 한다는 것은 컴퓨터에서 코드 실행시 변수를 위한 메모리 공간을 할당한다는 의미를 내포한다. 

따라서, 변수는 이름, 값, 타입, 주소를 속성으로 가진다. 

 

package main

import "fmt"

func main(){
	var tmp int = 11

}

 

위 코드와 달리 쉽게 변수 선언을 하기 위해 초깃값을 생략하거나 변수 타입을 생략하는 등 다양한 선언이 가능하다. 

 

변수의 타입은 처음 변환한 타입에서 변환할 수 있다. Go언어는 다른 언어들과 달리 타입에 대한 자동 변환을 지원하지 않는다. 

따라서 연산하거나 대입을 위한 타입 변환을 수동적으로 해줘야한다. 

 

변수 타입 중 숫자 타입은 변수 크기에 따라서 표현할 수 있는 값의 범위가 다르다. 

실수 타입은 유효 자릿수가 정해져 있으므로, 잘 확인하고 변수를 사용해야한다. 

 

텍스트 입출력 패키지 fmt

 

제목과 같이 Go에서는 fmt 패키지를 통해 데이터 표준 입출력을 할 수 있다. 

이때, 표준 입출력이란 터미널에서 데이터를 출력하고 입력하는 것을 말한다. 

 

표준 출력 함수로 Print(), Printf(), Println()을 사용할 수 있다. 

표준 입력 함수로 Scan(), Scanf(), Scanln()을 사용할 수 있다. 

 

변수를 출력할 때, 서식 문자를 활용해 최소 출력 너비 및 소숫점 이하로 몇개의 숫자까지 표현하는지 등 다양한 형식으로 출력할 수 있다. 

 

서식 문자 %v를 사용할 경우, 모든 타입의 기본 서식으로 출력할 수 있다. 

 

입력받을 때, 에러 발생시 표준 입력 스트림을 지우는 것이 좋다. 

 

 

 

연산자

 

C와 같이 산술 연산자로 사칙 연산, 비트 연산, 시프트 연산자가 있다. 

 

만약 정수 타입 숫자에서 경계 값에서 연산할 경우 주의가 필요하다. 

 

실수 타입에 대해 값의 같음을 확인하는 == 연산자 사용시, 정상적으로 동작하지 않을 수 있다. 

 

복합 대입 연산자를 통해 연산을 간편하게 줄여 사용할 수 있다. 

 

 

함수

 

함수는 한편으로는 코드 블럭 단위이다. 

 

함수를 사용하면 코드 재사용을 용이하게 할 수 있다. 

 

반환값이 여러개인 함수를 멀티 반환 함수라 하며, 함수 선언할 때, 반환 타입을 소괄호로 묶어 표시한다. 

 

함수는 다음과 같이 정의할 수 있다. 

 

func Sub(a int, b int) int {
	return a - b
}

 

 

 

 

 

해당 글은 [Tucker의 Go 언어 프로그래밍] 3장~7장을 읽고 공부한 글입니다. 

 

 

프로그램은 무엇인가?

컴퓨터가 수행해야 될 명령과 순서를 쓴 문서이다.

글이 어떤 언어로 되어있냐에 따라 다르다.

어떤 프로그래밍 언어냐 따라 다르다.

 

컴퓨터← 글로 된 문서(프로그램)을 받는다.

 

컴퓨터→ 내가 이걸 읽을 수 있는가?

 

인간의 언어 구조를 컴퓨터로 이해한다는 것은 어렵다.

프로그램을 컴퓨터가 바로 읽을 수는 없다.

 

컴퓨터는 프로그램 언어를 0, 1로 변환해서 읽어야 한다.

 

명령어 = OP(Operater)

 

명령어에 숫자를 넣은 것은 opcode다

 

ADD 3, 4   와 같은 것을 어셈블리어라고 한다. 

 

언어를 변환시켜줄 필요가 있다. 

 

 

고수준언어를 컴퓨터 기계어로 변환하는 변환기는 컴파일러라고 한다.

 

결국 프로그램은 실행파일이라고 한다. == .exe파일

 

코딩해서 컴파일 하는 과정을 빌드(변환)이라고한다. 이렇게 하면 기계어로 바뀜

 

역변환도 가능하다.

 

해커들은 기계어만 가지고도 어떤 프로그램인지 알 수 있고, 고칠 수 있다.

그러나 굉장히 어렵다. 그러나 가능하다.


프로그램 언어란?

 

고급언어/저급언어로 나뉜다. 

 

고급언어에는 c, c++, go와 같은 컴파일 언어와 Java, C#, Python, javascript와 같은 동적 언어가 있다. 

 

c, c++, go

  • 컴파일 언어
  • 코딩→ 빌드→ 기계어
  • 먹기전에 돈까스 다 잘라놓고 먹는사람
  • 실행 속도가 빠름

 

Java, C#, Python, javascript

  • 동적 언어
  • 코딩→ 빌드→
  • 기계어가 나오지 않음
  • 먹을때 하나씩 자르면서 먹는 사람
  • 실행 속도가 좀 느리다.


C, C++, Go언어의 특징

  • 컴파일 언어
  • 프로그래밍 과정
    • 코딩→빌드(컴파일러라는 프로그래머가 코딩한 문서를 기계어로 변환함)→ 실행파일(기계어1, 0)
    • 대부분의 고수준 언어는 역변환 과정이 불가능하다.

C#, Java, Python언어의 특징 

  • 동적 언어
  • 코딩→ 빌드 필요(Java, C#)→중간 언어= 문서임→ 기계어로 변환⇒ 실행 중간에 변환을 하는 것을 동적 언어라고 한다.

이런 구분이 왜 생겨났을까?

 

컴파일 언어는 속도가 빠르다.

동적 언어는 중간 중간 변환 하기 때문에 속도가 느리다.

 

컴파일 언어가 좋은데 왜 동적 언어들이 생겨났을까?

 

컴파일 언어는 각 플랫폼 별로 다른 변환이 필요했다.

⇒ 각 프로그램 별로 실행 파일이 모두 달랐어야 했다.

⇒각 플랫폼 별로 빌드가 필요하다.

 

과거에는 굉장히 많은 CPU회사가 있었다.

 

자연어를 기계어로 변환 할 때의 어셈블리어의 각 명령어 마다 번호를 부여하게 되는데, 문제는 칩셋 제조사 마다 이 번호가 다 달랐다.

결국, 어떤 칩셋을 사용하냐에 따라 다르게 동작해야 했다.

 

인텔 CPU

  • 칩셋의 발전 과정 8086-80286-80386-80486- 펜티엄, , , , I3, I5, I7(요즘 나오는 것)

새로운 CPU가 나올때 OP코드도 추가된다.

같은 인텔 계열 칩셋이라도 어떻게 변환하냐에 따라 프로그램이 달라진다.

 

OS- 윈도우즈, Mac, Linux 등 각 OS마다 동작 방식이 다르고, 실행파일 형식도 다르고 실행하는 방법도 다르다.

 

CPU, OS에 따라 컴파일 변환 과정이 다 달랐다.

 

옛날 게임들- Windows밖에 안돼 등.. 문제가 있었다. 

이런거 해결을 위해 나온것 = 동적 언어

프로그램을 만들어 놓으면 실행주체가 어떤 프로그램인지 파악해서 그때 그때 변환 하는 것임.

 

Java 언어의 특징 

  • 코딩→ 결과 → 빌드 → .JAR
  • 플랫폼에 따라 실행 가능 하도록 알아서 변환된다.
  • 컴파일 언어에 비해서 속도가 떨어진다는 문제점이 있었다.
  • C++이 자바보다 빠르다고 말하는 사람이 많다.
  • 언어적으로 완성도가 높다.
  • 라이브러리 지원이 많다.
  • 생산성이 좋다. (C# 또한)

C, C++ 언어의 특징 

  • 사용법이 까다롭고 라이브러리가 좀 ,, 자바보다 못하다.
  • 속도는 자바와 거의 비슷하다.

 

첫 언어로 선택할만한 언어에 어떤 언어가 있는가.?

 

C언어

  • 기본, 근간, simple, 포인터

C#

  • 첫 언어로 무난하다.
  • Windows에서 잘 돌아간다.

Python

  • 언어구조 단순, 짜임새가 좋다, 언어의 완성도가 높다.
  • OOP적 측면에서 봤을때 완전 좋다.
  • 인터프리터 언어
  • 속도가 떨어진다.

Javascript

  • 웹쪽 언어
  • 자바스크립트를 첫 언어로 쓰기에는 안좋다.
  • 완성도가 떨어진다.
  • 웹쪽 쓸 때는 필수

 

해당 글은 [Tucker의 Go 언어 프로그래밍] 2장을 읽고 공부한 글입니다. 

트랜지스터(삼 석, 다리 세게 달리고 가운데가 긺. )

  • 컴퓨터의 가장 기본적인 요소임
  • 컴퓨터는 수천, 수억 개의 수많은 트랜지스터들로 만들어져 있음
  • CPU는 트랜지스터 덩어리임
  • 컴퓨터에서는 트랜지스터를 전기만 가지고 스위치의 역할을 하는 것으로 쓴다.
  • 전기적 신호로 작동함. (진짜 스위치는 물리적인 힘으로 껏다 켰다 해야함.)
  • 1 비트는 하나의 트랜지스터라고 보면 된다.

발광 다이오드= LED

  • 성질이 다른 두 개의 실리콘을 겹쳐서 N,P다이오드를 만들어서 건전지를 달면 전기가 흘러서 불이 들어옴
  • 발광 다이오드에서 좀더 발전해서 트랜지스터가 된다.

 

트랜지스터로 논리소자를 만들 수 있다.

 

BOOL 대수 - AND, OR, NOT

 

도체 - 전기가 흐르는 물질 - 구리, 철, 금, 물, 몸

부도체 - 그릇, 세라믹, 돌

 

부도체는 저항이 무한대에 가깝다.

도체는 저항이 매우 작다. = 0에 가깝다.

 

반도체는 도체로 됐다가 부도체로 됐다가 하는 애다.


트랜지스터 → 논리소자 → 계산기 → 컴퓨터

 

컴퓨터(CPU) ← 트랜지스터 ← 실리콘 ← 규소 ← 모래

 

컴퓨터를 발명해낸 사람들은 아래와 같다. 

 

튜링

  업적

  • 튜링테스트(AI를 테스트 하는 기법)
  • 튜링 기계 (상상 속의 기계)
    • 한줄씩 명령을 수행하는 기계가 있으면 연산을 수행하기 좋겠다 라는 생각을 했다. 

폰노이만

  업적

  • 우주 최강의 두뇌 소유자
  • 폰 노이만 기계
    • 전자계산기, 전자시계, 네비게이션과 컴퓨터는 차이가 있다.
    • 컴퓨터는 프로그램을 교체하면서 모든걸 다 할 수 있었다.
    • 튜링 기계랑 비슷한 기계를 만듦
    • 초창기 컴퓨터의 구조와 비슷함


컴퓨터란, 명령을 하나씩 순서대로 수행하는 기계다.

명령: Add, Sub, Div, etc,,

CPU의 각 코어는 코어마다 명령을 하나씩 수행함

 

IP(instruction point)

 

프로그램은 어떤 명령을 어떤 순서로 수행할 것인지 적어놓은 것을 말한다.

 

컴퓨터는 1, 0밖에 모르고 add 등 밖에 못한다.

 

인간이 표현하는 그림, 음악, 문자는 숫자로 표현 가능하다.

 

A=65, a=97 , , , (ASCII-255개 문자에 코드)

 

1byte = 8bit 2^8은 256임

0-255 개 만 표현할 수 있다.

 

영문자만 표현할 수는 없어서 확장으로 UNICode 2byte 를 많이 사용하고 있음.

 

이미지는 모니터의 1080*720은 가로에 1080픽셀이 있다.

 

색 → 숫자로 RGB 로 표현할 수 있음

 

점하나에 LED3개가 묶여있다. RGB(LED)

 

R - 255, G - 255, B - 255, A - 투명도

4byte숫자를 쭉 나열하면 화면을 보여줄 수 있다.

 

소리는 주파수에 따른 세기를 통해 나타낼 수 있다.

모든 숫자는 이진수로 표현할 수 있다.

 


 

하드웨어란?

비유

요리할 때 레시피가 필요하다. → 요리하는 방법이 적혀있다. ⇒ 프로그램이다.

요리 재료가 필요하다. → 마트가 필요함→ 마트에 버스타고 간다.

 

이때 마트는 하드디스크임(HDD), 버스는 진짜 버스임

 

마트에서 사와서 냉장고에 재료를 넣는다. (메모리) 마트보다 가까움

 

요리준비 끝.

 

필요한 만큼 마늘과 고기를 꺼내서 도마 위에 놓는다. = CACHE

이렇게 하는 이유는 효율적이기 때문이다.

이때, 도마는 Register 이다. (값을 딱 준비 시켜놓는 자리)

 

CPU는 요리하는 사람.

 

요리하는 도중에 마트에 가는 비효율적이고 시간이 오래 걸린다.

메모리에 가기도 그렇고 그래서 캐시를 쓴다.

 


 

컴퓨터 성능 3GHZ = 주파수

1초당 연산을 3G만큼 한다.

1초에 3 * 1024(GB) *. 1024(MB) *. 1024(KB) 만큼의 연산을 한다.

 

해당 글은 [Tucker의 Go 언어 프로그래밍] 1장을 읽고 공부한 글입니다. 

알아둘 것 

 

  • NVM(Node Version Manager)
    • Node.js의 버전을 관리하는 도구, 다양한 버전의 Node.js를 설치하게 도와줌

 

  • Nodejs의 특정 버전을 설치하고 싶은 경우
    • nvm 설치
    • 현재 사용중인 버전 확인
    • nvm으로 설치된 node.js 목록 확인
    • 특정 버전의 노드를 사용하는 명령어 입력
    • 특정 버전의 노드가 설치되어 있지 않은 경우, 설치 
#현재 사용중인 버전 확인
$nvm current

#nvm으로 설치된 node.js 목록 확인
$nvm ls

#특정 버전의 노드를 사용하는 명령어 입력
nvm use <version>

#특정 버전의 노드가 설치되어 있지 않은 경우, 설치 
npm install <version>

 

 

 

 

 

Detached Head: head가 branch로 부터 떨어져있는 상태를 말함. 

branch 를 통해서가 아닌 직접 다이렉트로 commit을 참조하고 있는 상태를 말함. 

 

git 에서 head는 단 하나만 존재하며, 시작점 같은 개념이라고 한다. 
head는 특정 branch를 가리키고 그 branch는 해당 branch의 마지막 commit을 가리킨다.
보통의 경우엔 head-> branch -> commit 의 참조순서를 가진다.

하지만 이 때, check out 명령어로 특정 커밋으로 check out할 경우, 깃은 참조하던 branch를 잃어버리고, 직접 특정 commit을 참조하는 detached head 상태가 된다.

git checkout <revision number>명령어를 사용해, 특정 커밋으로  check out할 경우 detached head상태가 된다.

출처: https://devcamus.tistory.com/6
고 한다. 근데 난 revision number 명령어를 사용해서 커밋하지 않았는데?;


 


아 내가 checkout 할 때 -b 옵션(브랜치 이름을 변경해서 가져올 수 있는 옵션, 로컬 저장소를 만들 수 있는 옵션) 혹은 -t(원격 브랜치를 이름 변경없이 로컬 저장소를 만들 수 있는 옵션)을 추가하여 명령어를 실행하지 않아서 임시로 해당 브랜치로 이동하게 되었고, 따라서 로컬 브랜치가 만들어지지 않았음. 그래서 HEAD detached at 상태였다.

git checkout -b 브랜치명  혹은 git checkout -t 브랜치명
명령어를 주면 로컬 브랜치를 만들 수 있다. 





 

'형상관리 > Git' 카테고리의 다른 글

[Git] 원격브랜치를 로컬환경에 가져오기  (0) 2024.08.15
[Git] 원본 저장소 원격 추가하기  (0) 2024.07.29
[Git]브랜치 관리  (1) 2024.01.31

https://school.programmers.co.kr/learn/courses/30/lessons/87946

 

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제설명

XX게임에는 피로도 시스템(0 이상의 정수로 표현합니다)이 있으며, 일정 피로도를 사용해서 던전을 탐험할 수 있습니다. 이때, 각 던전마다 탐험을 시작하기 위해 필요한 "최소 필요 피로도"와 던전 탐험을 마쳤을 때 소모되는 "소모 피로도"가 있습니다. "최소 필요 피로도"는 해당 던전을 탐험하기 위해 가지고 있어야 하는 최소한의 피로도를 나타내며, "소모 피로도"는 던전을 탐험한 후 소모되는 피로도를 나타냅니다. 예를 들어 "최소 필요 피로도" 80, "소모 피로도" 20인 던전을 탐험하기 위해서는 유저의 현재 남은 피로도는 80 이상 이어야 하며, 던전을 탐험한 후에는 피로도 20이 소모됩니다.

 

이 게임에는 하루에 한 번씩 탐험할 수 있는 던전이 여러개 있는데, 한 유저가 오늘 이 던전들을 최대한 많이 탐험하려 합니다. 유저의 현재 피로도 k와 각 던전별 "최소 필요 피로도", "소모 피로도"가 담긴 2차원 배열 dungeons 가 매개변수로 주어질 때, 유저가 탐험할수 있는 최대 던전 수를 return 하도록 solution 함수를 완성해주세요.

 

제한사항

k 1 이상 5,000 이하인 자연수입니다.

dungeons의 세로() 길이(, 던전의 개수) 1 이상 8 이하입니다.

dungeons의 가로() 길이는 2 입니다.

dungeons의 각 행은 각 던전의 ["최소 필요 피로도", "소모 피로도"] 입니다.

"최소 필요 피로도"는 항상 "소모 피로도"보다 크거나 같습니다.

"최소 필요 피로도" "소모 피로도" 1 이상 1,000 이하인 자연수입니다.

서로 다른 던전의 ["최소 필요 피로도", "소모 피로도"]가 서로 같을 수 있습니다.

입출력 예

k         dungeons         result

80        [[80,20],[50,40],[30,10]]      3

입출력 예 설명

현재 피로도는 80입니다.

 

만약, 첫 번째두 번째세 번째 던전 순서로 탐험한다면

 

현재 피로도는 80이며, 첫 번째 던전을 돌기위해 필요한 "최소 필요 피로도" 또한 80이므로, 첫 번째 던전을 탐험할 수 있습니다. 첫 번째 던전의 "소모 피로도" 20이므로, 던전을 탐험한 후 남은 피로도는 60입니다.

남은 피로도는 60이며, 두 번째 던전을 돌기위해 필요한 "최소 필요 피로도" 50이므로, 두 번째 던전을 탐험할 수 있습니다. 두 번째 던전의 "소모 피로도" 40이므로, 던전을 탐험한 후 남은 피로도는 20입니다.

남은 피로도는 20이며, 세 번째 던전을 돌기위해 필요한 "최소 필요 피로도" 30입니다. 따라서 세 번째 던전은 탐험할 수 없습니다.

 

만약, 첫 번째세 번째두 번째 던전 순서로 탐험한다면

 

현재 피로도는 80이며, 첫 번째 던전을 돌기위해 필요한 "최소 필요 피로도" 또한 80이므로, 첫 번째 던전을 탐험할 수 있습니다. 첫 번째 던전의 "소모 피로도" 20이므로, 던전을 탐험한 후 남은 피로도는 60입니다.

남은 피로도는 60이며, 세 번째 던전을 돌기위해 필요한 "최소 필요 피로도" 30이므로, 세 번째 던전을 탐험할 수 있습니다. 세 번째 던전의 "소모 피로도" 10이므로, 던전을 탐험한 후 남은 피로도는 50입니다.

남은 피로도는 50이며, 두 번째 던전을 돌기위해 필요한 "최소 필요 피로도" 50이므로, 두 번째 던전을 탐험할 수 있습니다. 두 번째 던전의 "소모 피로도" 40이므로, 던전을 탐험한 후 남은 피로도는 10입니다.

따라서 이 경우 세 던전을 모두 탐험할 수 있으며, 유저가 탐험할 수 있는 최대 던전 수는 3입니다.

 

문제 해결 방법

1. dungeons에서 모두 나올 수 있는 순서에 대해 경우의 수를 순열로 뽑는다.

2. 리스트를 하나 만들고, 순열로 뽑은 모든 경우의 수에 대해서 조건을 따져가면서 던전에 방문한 횟수를 카운트 하여 최종적으로 카운트 한 수를 해당 리스트에 추가한다. 

2-1. 위에서 말한 조건으로 각 던전의 최소 필요 피로도가  k와 같거나 커야지 던전에 방문할 수 있으니 해당하는 조건을 체크한다. 

2-2. 만약 k가 특정 던전에 방문할 수 있다면 k에서 소모 피로도를 빼준다. 

3. 2번에서 만든 리스트에서 max값을 구하여 출력한다. 

 

코드 구현

from itertools import permutations

def solution(k, dungeons):
    answer = -1
    
    cpk=k
    cases = list(permutations(dungeons, len(dungeons)))
    checkList=[]
    
    for i in range(len(cases)):
        cpK=k
        checkcheck = 0
        for j in range(len(cases[i])):
            if cpK >= cases[i][j][0]:
                cpK = cpK - cases[i][j][1]
                checkcheck += 1
            else:
                pass
            
            if j == len(cases[i])-1:
                checkList.append(checkcheck)

    answer = max(checkList)
    
    return answer

 

 

주석 포함 코드

 

더보기

 

from itertools import permutations

def solution(k, dungeons):
    answer = -1
    
    #print('k', k, 'dungeons', dungeons)
    # 던전마다 탐험을 시작하기 위해 필요한 "최소 필요 피로도"
    # 던전 탐험을 마쳤을 때 소모되는 "소모 피로도"
    
    #최소 필요 피로도"가 80, "소모 피로도"가 20인 던전을 탐험하기 위해서는 유저의 현재 남은 피로도는 80 이상 이어야 하며, 던전을 탐험한 후에는 피로도 20이 소모됨
    
    #하루에 한 번씩 탐험할 수 있는 던전이 여러개
    
    # 1. dungeons는 [0]기준 MAX를 뽑는다. 
    # 2. dungeons의 순열을 뽑는다. 
    
    
    cpk=k
    
    
    cases = list(permutations(dungeons, len(dungeons)))
    #print(cases)
    
    checkList=[]
    #print("")
    
    for i in range(len(cases)):
        #maxx = cases[i][0][0]
        cpK=k
        #print("1 cpK", cpK)
        checkcheck = 0
        #print('i', i, cases[i])
        for j in range(len(cases[i])):
            #print('j', j, cases[i][j])

            if cpK >= cases[i][j][0]:
                cpK = cpK - cases[i][j][1]
                #print('cpK', cpK)
                checkcheck += 1
            else:
                pass
            
            if j == len(cases[i])-1:
                checkList.append(checkcheck)
            
        #print("")
        #print("")


    #print(checkList)
            
    answer= max(checkList)
    
    return answer

 

 

 

 

 

 

 

 

시간/공간 복잡도

최악의 경우 O(N^2)

최적화 및 개선

하지않았다. 

어려웠던 점

안풀어본 문제유형(완전탐색)이라 완전 쫄았다. 완전탐색 문제를 풀기위해서 대략 어떤 알고리즘이 필요한지 찾아보고 일단은 대충이라도 공부했다. (요즘 좀 바쁨) 암튼 대충 이런저런 방법으로 생각해보다가 문제를 풀었다 .


진짜 내가 이 문제를 푼거에 대해서 아주 놀랍다 하하 박수 ~~~ 짝짝~~

생각보다 진짜 별거아니네 !!! 쫄지마 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

 

https://school.programmers.co.kr/learn/courses/30/lessons/12906

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제설명

배열 arr가 주어집니다. 배열 arr의 각 원소는 숫자 0부터 9까지로 이루어져 있습니다. 이때, 배열 arr에서 연속적으로 나타나는 숫자는 하나만 남기고 전부 제거하려고 합니다. , 제거된 후 남은 수들을 반환할 때는 배열 arr의 원소들의 순서를 유지해야 합니다. 예를 들면,

 

  • arr = [1, 1, 3, 3, 0, 1, 1] 이면 [1, 3, 0, 1] 을 return 합니다.
  • arr = [4, 4, 4, 3, 3] 이면 [4, 3] 을 return 합니다.


배열 arr에서 연속적으로 나타나는 숫자는 제거하고 남은 수들을 return 하는 solution 함수를 완성해 주세요.

 

제한사항

배열 arr의 크기 : 1,000,000 이하의 자연수

배열 arr의 원소의 크기 : 0보다 크거나 같고 9보다 작거나 같은 정수

입출력 예

arr       answer

[1,1,3,3,0,1,1]      [1,3,0,1]

[4,4,4,3,3]          [4,3]

입출력 예 설명

입출력 예 #1,2

문제의 예시와 같습니다.

문제 해결 방법

stack을 이용하여 문제를 푼다. 
1. stack 구실을 할 임의의 리스트를 하나 만든다. 

2. arr의 원소를 순회하면서 임의의 리스트에 첫번째 원소를 push한다. 

2-1. 첫번째 이후의 원소들은 임의의 리스트의 마지막에 push한 값을 pop을 통해 꺼낸다.

2-2. 2-1번을 통해 꺼낸 값과 현재 넣고자 하는 arr의 원소를 비교하여 값이 같으면 pass하고 같지 않으면 push 한다. 

코드 구현

 

1. 효율성 통과하지 못한 코드 

def solution(arr):
    answer = []
    
    # pivot 변수 = p
    # 이전 pivot을 기억하는 변수 = pre_p
    check = 0
    pre_p = arr[0]
    l=len(arr)
    for i in range(1, len(arr)):
        p = arr[i]
        #print('p', p, 'pre_p', pre_p)
        if pre_p == p:
            pre_p = p
            arr[i] = 10
            # '-'를 세는 변수 = check
            check+=1
        else:
            pre_p=p
    
    for i in range(check):
        arr.remove(10)
        
    answer = arr
    return answer

 

 

2. 효율성 통과한 코드

def solution(arr):
    stack = []
    
    for i in range(len(arr)):
        if i == 0:
            stack.append((arr[i]))
        else:
            top = stack.pop()
            stack.append(top)
            if arr[i]==top:
                pass
            else:
                stack.append(arr[i])
    
    return stack

 

시간/공간 복잡도

1. 효율성을 통과하지 못한 코드: O(N^2)

2. 효율성을 통과한 코드: O(N)  

최적화 및 개선

처음에 효율성을 통과하지 못한 코드에 대해서 중첩 되지 않는 for문을 썼는데 왜 시간복잡도 효율성이 통과되지 않는지 이해가 안갔다. 혹시 내가 stack자료구조를 고려하지 않고 코드를 작성해서 그 부분에서 오류가 나는건가? 싶었다. 그래서 코드를 stack자료구조를 고려해서 리스트를 stack화 해서 코드를 짰다. 확실히 pop함수를 사용해서 그런가 편리하고 뒷처리를 해주지 않아도 되는 점이 깔끔하고 좋았다. 그리고 효율성에도 통과했다. 

 

그렇다면 1번 코드는 어디에서 효율성을 많이 잡아먹는가?

 

바로 for문에 있는 remove함수 때문이다. 

remove함수는 시간복잡도 O(N)을 잡아먹는다. 그런데 이걸 for문으로 처리하고있으니 시간복잡도가 O(N^2)이 되었던 것이였다. 

어려웠던 점

파이썬 각각의 함수들의 특성에 대해서는 잘 몰랐는데, 이렇게 문제를 풀면서 기억에 각인도 시키고 하니 좋다. 

어쩜 코딩테스트 문제들은 하나같이 문제 푸는 사람이 그 문제를 풀기위해서 알아야 하는것을 모른다면, 그것에 대해서 스스로 알게되지 않고서야 절대 문제를 못풀게끔 되어있는게 너무 신기하다. 이제야 드는 생각인데, 코딩테스트나 알고리즘 공부 어쩌면 좋은 제도일지도 모르겠다는 생각이 든다.  

https://school.programmers.co.kr/learn/courses/30/lessons/42839

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제설명

한자리 숫자가 적힌 종이 조각이 흩어져있습니다. 흩어진 종이 조각을 붙여 소수를 몇 개 만들 수 있는지 알아내려 합니다.

 

각 종이 조각에 적힌 숫자가 적힌 문자열 numbers가 주어졌을 때, 종이 조각으로 만들 수 있는 소수가 몇 개인지 return 하도록 solution 함수를 완성해주세요.

 

제한사항

numbers는 길이 1 이상 7 이하인 문자열입니다.

numbers 0~9까지 숫자만으로 이루어져 있습니다.

"013" 0, 1, 3 숫자가 적힌 종이 조각이 흩어져있다는 의미입니다.

입출력 예

numbers return

"17"      3

"011"    2

입출력 예 설명

예제 #1

[1, 7]으로는 소수 [7, 17, 71]를 만들 수 있습니다.

 

예제 #2

[0, 1, 1]으로는 소수 [11, 101]를 만들 수 있습니다.

 

11 011은 같은 숫자로 취급합니다.

문제 해결 방법

1. numbers 문자열을 문자로 떼내어 리스트에 정리한다. 

2. 정리한 리스트를 permutations함수를 통해 각 원소들을 통해 만들 수 있는 조합 모든 경우(한자리, 두자리, 세자리 ,, numbers의 길이만큼의 자리)를 리스트에 정리한다. 

3. 소수판별 함수를 만들어서 위의 리스트 원소들을 대상으로 소수 판별을 한다. 

4. 결과 출력

코드 구현

from itertools import permutations

def solution(numbers):
    answer = 0
    numbers= str(numbers)
    Nlist=[]
    
    for i in range(len(numbers)):
        Nlist.append(str(numbers[i]))
        
    totalList = []
    for i in range(len(numbers)):
        if i == len(numbers):
            break
        totalList += list(map(''.join, (permutations(Nlist, i+1))))
    
    totalList=list(map(int, totalList))
    totalList=set(totalList)
    totalList=list(totalList)
    
    if 0 in totalList:
        totalList.remove(0)
    
    if 1 in totalList:
        totalList.remove(1)
    
    
    def primenumber(x):
        # 2부터 x-1까지 순회
        for i in range(2, x):
            if x % i == 0:
                # 하나라도 나눠 떨어지면 False 반환
                return False
        # 아무것도 나눠 떨어지는게 없으면 True 반환
        return True
    
    for i in range(len(totalList)):
        if primenumber(totalList[i])== True:
            answer+=1
            
    
# 어둠의 잔해 소수 판별기 
    
#     topic=2
#     check=0

#     for i in range(len(totalList)):
#         while 1:
#             if totalList[i] == 0:
#                 # 원소 0은 pass
#                 pass
            
#             if totalList[i] % topic == 0:
#                 check+=1
#                 if check ==1:
#                     break
#                 topic+=1   
#             else:
#                 topic+=1
            
#             if topic == totalList[i]:
#                 topic = 2
#                 break
                
#         if check == 1:
#             answer+=1
#             check=0
#         else:
#             check=0
#             pass
        

    
    return answer

시간/공간 복잡도

O(N)

최적화 및 개선

하지않음 

어려웠던 점

문제를 어떻게 풀어야하겠다는 것은 알겠지만서도, 자잘한 문법, 함수 사용법을 정확하게 몰라서 좀 시간이 걸렸다. 

생각하는데로 출력하고 활용하는것이 좀 어려웠다. 

 

특히 튜플 자료형, join함수, map함수, map객체, set함수 등에 대해서 잘 몰라서 새로 찾아봤다. 

 

소수를 찾는 로직도 예전에 문제를 한번 풀어봤었는 경험으로 코드를 짜봤는데(어둠의 잔해 소수 판별기), 시간초과가 나왔다. 왜그럴까??? 빈틈없이 짰다고 생각했는데, 시간날때 다시 한번 봐야겠다.  

https://school.programmers.co.kr/learn/courses/30/lessons/42840#

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제 설명

수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 1번 문제부터 마지막 문제까지 다음과 같이 찍습니다.

 

1번 수포자가 찍는 방식: 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ...

2번 수포자가 찍는 방식: 2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5, ...

3번 수포자가 찍는 방식: 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, ...

 

1번 문제부터 마지막 문제까지의 정답이 순서대로 들은 배열 answers가 주어졌을 때, 가장 많은 문제를 맞힌 사람이 누구인지 배열에 담아 return 하도록 solution 함수를 작성해주세요.

 

제한 조건

시험은 최대 10,000 문제로 구성되어있습니다.

문제의 정답은 1, 2, 3, 4, 5중 하나입니다.

가장 높은 점수를 받은 사람이 여럿일 경우, return하는 값을 오름차순 정렬해주세요.

입출력 예

answers return

[1,2,3,4,5]          [1]

[1,3,2,4,2]          [1,2,3]

입출력 예 설명

입출력 예 #1

 

수포자 1은 모든 문제를 맞혔습니다.

수포자 2는 모든 문제를 틀렸습니다.

수포자 3은 모든 문제를 틀렸습니다.

따라서 가장 문제를 많이 맞힌 사람은 수포자 1입니다.

 

입출력 예 #2

 

모든 사람이 2문제씩을 맞췄습니다.

문제 해결 방법

1. 수포자 1, 2, 3의 정답 패턴이 들어있는 리스트 생성

2. 각각의 정답을 answers와 대조하여 각각의  score을 매김

3. score중에서 max가 있으면 해당 값을 answer리스트에 삽입, 만약 max값을 가지는 사람이 여러명이거나 셋다 값이 같다면 해당 케이스에 대해서 처리해줘야함

코드 구현

def solution(answers):
    answer = []
    
    l1=[1,2,3,4,5]
    l2=[2,1,2,3,2,4,2,5]
    l3=[3,3,1,1,2,2,4,4,5,5]
    
    len_a = len(answers)
    cnt = 0
    score1 = score2 = score3 = 0
    for i in range(len(answers)):
        cnt = i
        if cnt >= len(l1):
            cnt = cnt % len(l1)
        if l1[cnt] == answers[i]:
            score1+=1 
            
    cnt = 0  
    for i in range(len(answers)):
        cnt = i
        if cnt >= len(l2):
            cnt = cnt % len(l2)
        if l2[cnt] == answers[i]:
            score2+=1 

    cnt = 0
    for i in range(len(answers)):
        cnt = i
        if cnt >= len(l3):
            cnt = cnt % len(l3)
        if l3[cnt] == answers[i]:
            score3+=1 

    total_list=[]
    total_list.append(score1)
    total_list.append(score2)
    total_list.append(score3)
    
    if score1==score2==score3:
        answer.extend([1,2,3])
    else:
        maxx=(max(total_list))
        answer.append(total_list.index(max(total_list)) + 1)
        total_list[total_list.index(max(total_list))] = 0
        if maxx in total_list:
            answer.append(total_list.index(maxx)+1)

    return answer

시간/공간 복잡도

O(N)

최적화 및 개선

하지않음

어려웠던 점

문제 이해를 잘 못했어서 하루를 날렸다. 

세세한 조건 따질줄 아직 잘 모르는것 같다. 

그리고 조건을 따질 줄 안다 하더라도 이걸 이렇게까지 해야한다고? 싶은 생각에 자꾸 막히는듯 함

 

문제설명

명함 지갑을 만드는 회사에서 지갑의 크기를 정하려고 합니다. 다양한 모양과 크기의 명함들을 모두 수납할  있으면서, 작아서 들고 다니기 편한 지갑을 만들어야 합니다. 이러한 요건을 만족하는 지갑을 만들기 위해 디자인팀은 모든 명함의 가로 길이와 세로 길이를 조사했습니다.

아래 표는 4가지 명함의 가로 길이와 세로 길이를 나타냅니다.

명함 번호                  가로 길이                  세로 길이

1                  60               50

2                  30               70

3                  60               30

4                  80               40

가장  가로 길이와 세로 길이가 각각 80, 70이기 때문에 80(가로) x 70(세로) 크기의 지갑을 만들면 모든 명함들을 수납할  있습니다. 하지만 2 명함을 가로로 눕혀 수납한다면 80(가로) x 50(세로) 크기의 지갑으로 모든 명함들을 수납할  있습니다. 이때의 지갑 크기는 4000(=80 x 50)입니다.

모든 명함의 가로 길이와 세로 길이를 나타내는 2차원 배열 sizes 매개변수로 주어집니다. 모든 명함을 수납할  있는 가장 작은 지갑을 만들 , 지갑의크기를 return 하도록 solution 함수를 완성해주세요.

 

문제 해결 방법

1. sizes 리스트에서 가로가 세로보다 작으면 위치를 바꿔준다.

2. sizes리스트의 모든 가로길이중에서 가장 큰 값, 해당 리스트의 모든 세로 길이 중에서 가장 큰 값

3. 두 값의 곱을 출력한다.

코드 구현

def solution(sizes):
    answer = 0
    tmp=0
    
    for i in range(len(sizes)):
        if sizes[i][0] < sizes[i][1]:
            tmp=sizes[i][0]
            sizes[i][0]=sizes[i][1]
            sizes[i][1]=tmp
    
    wMax=0
    lMax=sizes[0][1]
    
    for i in range(len(sizes)):
        if sizes[i][0] > wMax:
            wMax=sizes[i][0]
        
        if sizes[i][1] > lMax:
            lMax = sizes[i][1]
    
    answer = wMax * lMax

    return answer

 

 

시간/공간 복잡도

O(N)

최적화 및 개선

하지않음

어려웠던 점

없음

+ Recent posts