7. 배칭

드로우 콜에 대해서 알았다면, 이제 이것을 줄이는 방법을 알아야 한다. 가장 효율적인 방법으로 배칭이 있다. 효율적인 방법이라고 한 것은 여러의 배치를 하나로 묶어서 하나의 배치로 만드는 것이 바로 배칭인 것이다.  한 가지 예를 들어보면 오브젝트가 3개 있다면 원래는 3개의 드로우 콜 즉, 3개의 배치가 필요하지만 조건에 따라서 1개까지 줄이는 것이다. 메시가 서로 다른 오브젝트이지만 같은 머테리얼을 사용하면 하나의 배치로 만들 수 있다. 

배칭을 위해서는 다른메시를 이용하더라도 머티리얼을 공유해서 사용해야 한다. 파츠가 여러 개인 경우 메시는 각각 다르지만 하나의 머티리얼을 통해 색상을 입히는 것이다. 이렇게 하기 위해서는 여러 장의 텍스처를 하나를 묶어 텍스처 아틀라스 기법으로 하나의 텍스처로 여러 메시들이 사용할 수 있게 하는 것이다.

같은 머테리얼이라는 의미는 동일한 인스턴스를 말하며, 같은 텍스처를 사용하는 머테리얼이지만 그것이 2개라면 같은 인스턴스가 아닌 것이다.

다른 머테리얼

이러한 이유로 코드상에서 머티리얼을 접근할때 유의할 점이있다.  머테리얼 색상을 바꾸는 코드는 GetComponent<Renderer>().material.color = Color.red;을 사용하면 색상을 바꿀 수 있다. 하지만 이 코드를 사용할 때마다 계속해서 새로운 머테리얼을 복사 생성하게 된다. 그러면 다른 머테리얼의 인스턴스를 생성하는 것이다. 하지만 같은 인스턴스를 사용하는 방법도 있다. 머테리얼의 속성을 바꾸는 Renderer.sharedMaterial을 사용하면 된다. 물론 상황에 따라 사용하겠지만 한 가지 예시로,

아래 그림처럼 스켈레톤 몬스터는 모두 같은 머티리얼을 사용하고 있다. 그러면 현재는 한 개의 인스턴스가 있는 것이다. 그런데 플레이어가 스켈레톤을 공격하면 빨간색으로 피격 효과를  받게 되는데 같은 인스턴스를 공유하고 있기 때문에 피격을 당하지 않은 몬스터까지도 피격 효과(빨갛게) 변할 것이다. 

이것은 분명 개발 기획의도는 아닐 것이다. 그렇다면 어쩔 수 없이 몬스터마다 각각 다른 인스턴스를 생성해서 적용해야 하는 걸까?

2019/10/03 - [유니티/레퍼런스] - 유니티)MaterialPropertyBlock

 

유니티)MaterialPropertyBlock

sharedMaterial 머테리얼의 속성을 변경할때 SharedMaterial으로 색상을 바꾼다던지 쉐이더코드의 프로퍼티값들을 변경한다. 그런데 이 런타임중에 변경된 머테리얼의 값들은 종료해도 바뀐 값 그대로 유지된다...

funfunhanblog.tistory.com

MaterialPropertyBlock를 이용하면 객체의 변화를 주는 동안만 배칭이 되지 않고 작업이 끝나면 다시 배칭을 하는 방법이다.

 

8.  스태틱배칭

스태틱 배칭은 말 그대로 정적인 오브젝트 즉 움직이지 않는 오브젝트를 위한 기법이다. 주로 배경 오브젝트들이 해당되는데 이 기법을 이용하려면  Static 플래그를 켜야 한다. 이 플래그를 켜야 유니티가 이 오브젝트는 움직이지 않는 스태틱 오브젝트라는 것을 알 수 있기 때문이다. 

그런 후 다른 작업 없이 게임을 시작하면 자동으로 유니티는 스태틱 플래그가 켜진 오브젝트를 배칭 처리 작업을 진행한다. 오브젝트 버텍스가 많을수록 렌더링 연산 비용이 크다. 당연히 버텍스 수가 많으면 런타임 과정 중에 부담이 크다. 하지만 스태틱 배칭 된 오브젝트는 런타임에 연산이 이루어지지 않는 게 장점이 되는 것이다.

드로우콜수를 줄이기 위해 오브젝트들을 합쳐 내부적으로 하나의 메시로 만들어준다. 만일 3개의 오브젝트가 1개의 메시만 사용하더라도 3개의 메시를 합친 만큼 추가 메모리가 필요하게 되는 것이다. (내 생각에는 SpriteAtlas처럼 생각하면 될듯하다)

물론 이 작업은 유니티가 이러한 정보들을 저장해 야하기 때문에 메모리가 조금 더 필요하게 된다. 렌더링(드로우 콜)이냐 메모리냐 이 논제는 최적화에서 자주 결정해야 할 사항이다.  스태틱 배칭을 간단하게 정의하자면

대상 :움직이지 않는 오브젝트

장점 : 드로우콜 감소

단점 : 메모리 증가

9.  다이내믹 배칭

동적으로 움직이는 오브젝트들끼리 배칭 처리를 하는 기능이다. 동일한 머티리얼을 사용하며 자동으로 배칭이 이루어진다. 배칭 처리는 런타임상에 이루어지며 Static플래그가 체크되어 있지 않는 오브젝트들의 버텍스들을 모아서 합쳐주는 과정을 거친다. 이러한 버텍스들을 모아서 다이내믹 배칭에 쓰이는 버텍스 버퍼와 인덱스 버퍼에 담는다. GPU는 이를 가져가서 렌더링 하는 것이다. 매프 레임 데이터 구축과 갱신이 발생하기 때문에 오버헤드가 발생하게 된다. 다이내믹은 자동으로 이루어지지만 여러 가지 조건들이 있다.

1. 버텍스 900개 이하로 된 메시로만 적용된다.

2. 트랜스폼을 미러링 한 오브젝트들은 배칭 되지 않는다.(예를 들어 Scale값이 1인 오브젝트를 -1로 적용했을 때)

3. 다른 머티리얼 인스턴스를 사용하면 같이 배칭 되지 않는다.

4. 라이트맵이 있는 오브젝트는 추가 렌더러 파라미터를 가지는데, 일반적으로 동적으로 라이트 매핑된 오브젝트가 완전히 동일한 라이트맵의 지점에 있어야 배칭 된다.

5. 멀티 패스 셰이더를 쓰면 배칭이 되지 않는다.

스태틱 배칭은 버텍스 쉐이더에서 월드 스페이스로의 변환이 이루어진다. 즉 GPU에서 연산이 된다. 하지만 다이내믹 배칭은 실시간으로 오브젝트의 위치가 변환되기 때문에 CPU에서 연산이 이루어진다. 

10.  2D 스프라이트 배칭

2D도 배칭 작업이 가능하다. 텍스처 아틀라스 기법처럼 여러 이미지들을 한 이미지에 모아서 사용하는 방법과 SpriteAtlas를 사용하여 배칭 처리한다.

2019/01/09 - [유니티/최적화] - 유니티) 아틀라스 Sprite Atlas이용해 드로우콜을 줄여보자

 

유니티) 아틀라스 Sprite Atlas이용해 드로우콜을 줄여보자

스프라이트 아틀라스 유니티에서 아틀라스는 텍스처를 한곳에 모은 한장의 큰 텍스처라고 할수있다. 텍스처 하나씩 따로따로 사용하고 관리하는것은 효율적이지 못하다. 아틀라스를 사용하면 드로우콜을 줄일 수..

funfunhanblog.tistory.com

11.  GPU 인스턴 싱

적은 수의 드로우 콜을 사용하여 동일한 메시의 여러 복제본을 한 번에 그리거나 렌더링 한다. 특히 씬에서 반복적으로 나타나는 건물, 나무, 풀 등의 오브젝트를 보여줄 때 좋다. 또 같은 메시를 사용하더라도 간단한 변화 컬러, 스케일 등의 변화를 줄 수 있다. 별도의 메시를 메시를 생성하지 않기에(트랜스폼 정보를 별도의 버퍼에 저장) 다이내믹 배칭과 스태틱 배칭보다 오버헤드가 적다.

https://docs.unity3d.com/kr/2017.4/Manual/GPUInstancing.html

반응형

 

1. 드로우콜  이란

간단하게 CPU가 GPU에게 렌더링 작업을 수행하도록 명령을 하는것이다.

게임은 실시간 렌더링 어플리케이션이다. 

실시간으로 렌더링을 수행하기에, 한 프레임의 렌더링은 오브젝트를 하나하나 그릴때마다 여러 정보들을 CPU에서 GPU로 전달하여 그리도록 명령한다.

CPU가 중앙처리 장치인 만큼 GPU에게 명령하기 떄문에 CPU의 의해 핸들링 되는 구조이다.

여기서 알아야 할 것은 CPU와 GPU는 각각 자신들이 메모리 공간을 가지고 있다. CPU의 메모리는 RAM이 주로 사용된다. 즉 이 RAM에 각종 데이터들이 담기고 CPU가 이를 이용하여 연산을 수행하게 된다. 그래픽 처리도 GPU와 VRAM을 나누어 관리한다.

보통 모바일기기에서는 CPU와 GPU메모리를 물리적으로 나누지 않는다.(하나의 물리적인 메모리를 논리적으로 나누어 사용)

드로우 콜은 렌더의 상태를 알려주는 명령과 CPU가 GPU에게 그리라는 명령(DP Call)까지이며, 이런 과정은 한번에 보내는 것이 아니라 순차적으로 보내게된다. 이런 과정이 반복되며 화면에 오브젝트를 렌더링하게된다.

2. 데이터와 명령의 흐름

데이터의 흐름 : Storage(HDD, SDD ,SD) -> CPU메모리 -> GPU메모리 (메시정보, 텍스처, 등등)

드로우콜을 이해 하려면 데이터와 명령의 흐름을 알아야한다. 먼저 메시,텍스처 등 렌더링에 필요한 데이터들은 저장소 흔히 알고있는 HDD,SDD,SD에 먼저 위치한다. 그러고 CPU는 이 데이터들을 파싱하여 CPU메모리에 데이터를 옮긴다. 그 그런 후 마지막으로 GPU는 CPU의 메모리의 데이터들을 GPU메모리에 복사를 하게된다.

예를들어 GPU가 메시를 렌더링할 때 지오메트리 데이터를  GPU메모리에서 가져와 렌더링하게 된다. (GPU메모리에 렌더링에 필요한 데이터가 있다고 보면 됨)

메모리를 가져오고 전달하는 과정을 매프레임 때마다 하는것은 성능저하가 올 수 있기 때문에 특정 시점(로딩 시점, 씬전환시점)에 메모리 데이터를 올려 사용하도록 하는게 좋다. 계속해서 사용하는 데이터라면 메모리에 계속 올려두고 사용하고 그럴필요가 없는 메모리라면 데이터를 해제해 메모리 부담이 없도록 한다. 메모리에 영향이 없다면, 특정시점에 한번에 해제하는 것도 방법이다. 

3. 커맨드 버퍼 (Command Buffer)

렌더링은 CPU가 바로 GPU에 명령을 보낸다고 생각하지만 중간에 GPU가 할일을 보관하는 중재자가 있다. CPU와 GPU는 병렬작업을 통해 수행하는데 이러한 과정을 중재하는 커맨드버퍼가 있다. CPU가 GPU에게 명령을 하는 순간 GPU가 다른 일을 하고 있을 수 있기 때문에 그 명령을 쌓아 놓고 순차적으로 GPU가 처리 할 수 있도록 한다.  

4. CPU의 성능에 의존되는 드로우콜

렌더링이기 때문에 드로우콜은 CPU보다는 GPU의 영향이 크다고 생각하지만, GPU가 그리기 위한 신호들을 모두 CPU가 GPU에 맞게 변형하여 보내게된다. 이런 과정들은 곧 CPU바운더리의 오버헤드이며, 텍스쳐의 크기를 줄이거나, 폴리곤 수를 줄인다고 해서 드로우콜의 성능이 좋아지는 것은 아니다. (횟수를 줄여야함) 

5. 배치와 SetPass Call

드로우콜의 발생조건을 이해하기 전에 먼저 배치(Batch)와 SetPass를 알아야한다. 배치는 각각의 드로우콜 사이에서 그래픽스 드라이버 유효성 체크를 진행할때, GPU에 의해 접그되어지는  리소스들을 변경하는 일련의 작업들을 총칭한다. (드로우콜과 혼용하여 사용하지만 드로우콜을 포함하는 상위 개념인것이다.) SetPass는 쉐이더로 인한 렌더링 패스 횟수를 의미하고 쉐이더의 변경 시 SetPass카운트는 증가하게된다. 드로우콜이 일어날때 상태 변경의 발생 여부로 이해하면 된다. (메시 변경은 포함하지 않음) 

유니티 Stats를 보면 간단하게 몇번의 배치가 됐는지 볼수 있다.

6. 드로우콜의 발생 조건

오브젝트 하나를 그릴때 메시1개, 머테리얼도 1개로 이루어져있다면 배치는 1이다.(드로우콜 한번), 하지만 하나의 오브젝트가 여러 파츠로 나눠져있고, 메시가 여러개이면 하나의 머테리얼을 공유했다고 해도 파츠 수 만큼 드로우콜이 발생한다.  이러한 오브젝트가 여러개있다면 파츠수 x 오브젝트수  = 드로우콜 수 가되는것이다. 때로는 당연히 성능에 많은 영향을 미칠수 있다. 메시가 여러개인 경우말고도 머테리얼이 여러개 인 경우, 툰쉐이딩 처럼 외각선을 그리기위해 멀티패스로 이루어져있는 쉐이더를 사용하면 두번의 드로우콜이 발생하게 된다.  

 

2019/01/09 - [유니티/최적화] - 유니티) 아틀라스 Sprite Atlas이용해 드로우콜을 줄여보자

 

 

유니티) 아틀라스 Sprite Atlas이용해 드로우콜을 줄여보자

스프라이트 아틀라스 유니티에서 아틀라스는 텍스처를 한곳에 모은 한장의 큰 텍스처라고 할수있다. 텍스처 하나씩 따로따로 사용하고 관리하는것은 효율적이지 못하다. 아틀라스를 사용하면 드로우콜을 줄일 수..

funfunhanblog.tistory.com

 

 

 

 

반응형

네트워크 구성TPC/IP 프로토콜

TCP/IP는 4단계 층으로 구성되는 계층적 프로토콜이다. 가장 하위 계층에는 네트워크 접속 계층이 있는 이는 하나의 계층으로 정의하기도 하고 또는물리 계층과 네트워크접속 계층, 2개의 계층으로 정의하기도 한다. 그 다음 패킷을 목적지까지 전송 책임을 수행하는 인터넷 프로토콜계층 그리고 종단간 신뢰성있는 연결을 수행하는 세그먼트 단위의 정보교환을 담당하는 전송 계층이 있으면 마지막으로 송수신지 응용 프로세스 사이 정보의 처리 기능을 수행하는 응용프로세스 계층이 있다.  

응용 계층

응용 계층은 원격의 프로세스 혹은 응용들 사이에 통신을 제공한다. HTTP, FTP, Telent, SMTP, SNMP기반의 응용서비스가 수행되는 계층이다.

  1. HTTP웹 서비스를 제공하는 응용 계층 프로토콜이다. 
  2. FTP파일 전송에 사용되는 프로토콜로서 파일의 전송을 위해 두개의 연결이 생성된다. 하나는 원격 시스템에 제어정보 송수신을 위해 연결된다. 그리고 연결 후 파일 전송을 위해 또 다른 연결이 수행된다.
  3. Telnet과 SMTP
  4. SNMP

전송 계층

1. TCP

전송 계층 프로토콜은 TCP와 UDP가 있다.  TCP 프로토콜은 두 종단 호스트간에 신뢰적인 연결형 서비스를 제공하여, 전송메세지의 정확한 수신지 도착 여부의 확인을 보장한다. 즉 시간 초과와 오류 재전송 그리고 데이터 흐름제어 기능이 제공된다.

네트워크 계층인 IP계층에서는 비연결형을 지향하므로 네트워크에 대한 에러제어와 흐름제어 기능을 수행하지 않기 때문에 TCP전송계층에서 에러제어와 흐름제어 기능이 제공된다. 

2. UDP

UDP프로토콜은 비연결형 서비스를 지원한다. UDP의 특징은 수신측에 패킷이 도착했는지 확인 여부를 보장하지 않으며 흐름제어의 기능을 제공하지 않는 비신뢰적인 서비스를 제공한다.  그러므로 수신된 데이터 훼손에 따른 무결성을 보장받지 못하므로 암호화기술이 적용될 수 있다. 네트워크 혼잡 시에 데이터 일부가 소실된다 하더라도 확인 작업이나 재전송 서비스가 지원되지 않는 특징을 가진다. UDP서비스는 제어용의 작은 메세지 혹은 재전송이 필요 없는 동영상 정보전송에는 적절한 서비스가 될 수 있다.

 

반응형

'STUDY > 네트워크' 카테고리의 다른 글

[네트워크] 멀티스레드 #1  (0) 2021.09.23
[네트워크] 유니티 네트워크 공부#1  (0) 2021.08.09
네트워크) 네트워크 구성  (0) 2019.11.13

클라이언트 프로그래머(초짜)지만 업무에 네트워크의 기본적인 지식은 필요하다고 생각되어 오늘부터 공부를 시작해보려고 한다!

네트워크

네트워크 구성

네트워크를 구축한다는 것은 사용자와 홈 그리고 사무실 등을 물리적 통신 설비를 기반으로 표준 통신 프로토콜로 연결하여 네트워크를 구축하는 것을 의미한다. 또한 네트워크는 또 다른 네트워크로 연결되어 거대한 인터넷으로 구성된다.

네트워크를 구성하는 물리적인 개념에서 하드웨어기반의 구성요소가 필요한데, 그 예로 라우터, 스위치, 이더넷 카드, 커넥터 허브 등이 있고, 서버 시스템과 개인용 컴퓨터 같은 호스등이 있다.

 

 

네트워크 구성요소 기능
라우터 IP주소기반 다른 네트워크와 통신 가능 장비
스위치 이더넷 주소기반 다음 목적지 회선 선택 장비
커넥터(RJ-45) 다양한 통신장비를 네트워크로 연결
이더넷 카드 단말기에 연결되어 데이터 송수신 역할
모뎀,허브,공유기 데이터전송을 위한 통신 주변 장치

네트워크를 구성하게 되면 거리와 공간의 제약을 극복하여 많은 정보기술의 다양한 장점을 활용할 수 있다. 먼저, 같은 네트워크 스토리지와 백업 장치를 비롯한 하드웨어와 소프트웨어 자원들 그리고 수많은 데이터와 응용 프로그램들의 공유가 가능하다. 

 

TCP / IP 프로토콜

표준 네트워크 프로토콜 기반의 인터넷에서는 네트워크 주요 서비스인 이메일 서비스,포털서비스와 게임 등 실시간으로 정보를 주고받는 애플리케이션 서비스를 어디서든지 이용할수 있게 된다. 네트워크 구축을 위해 사용되는 표준 프로토콜은 인터넷에서 사용되는 TCP/IP 프로토콜이다. TCP/IP 프로토콜을 이용하여 여러 토폴로지 형태의 네트워크를 연결한 것이 인터넷이다. 그리고 TCP/IP 프로토콜을 이용하여 내부 네트워크를 연결하여 내부 네트워크 사이 통신을 가능하게 한것이 인트라넷이다.

반응형

'STUDY > 네트워크' 카테고리의 다른 글

[네트워크] 멀티스레드 #1  (0) 2021.09.23
[네트워크] 유니티 네트워크 공부#1  (0) 2021.08.09
네트워크) TPC/IP 프로토콜  (0) 2019.11.17

sharedMaterial 

머테리얼의 속성을 변경할때 SharedMaterial으로 색상을 바꾼다던지 쉐이더코드의 프로퍼티값들을 변경한다. 그런데 이 런타임중에 변경된 머테리얼의 값들은 종료해도 바뀐 값 그대로 유지된다. 이것을 봤을때 Material에셋과 대응한다고 볼 수 있다.

같은 머테리얼을 가지고 있는 오브젝트

sharedMaterial을 사용하면 같은 머테리얼을 사용하는 모든 오브젝트가 변경된다. 예를들어 플레이어가 공격한 몬스터에게 림라이트효과를 주고 싶어 피격받은 몬스터의 Rim의 굵기를 변경했는데, 주위 모든 몬스터들의 Rim의 굵기가 변경되는것이다. => sharedMaterial을 참조하여 렌더링하기 때문 (배치 렌더링)

하지만 피격한 몬스터의 Rim만 변경을 원하기에 Renderer.material로 특정 오브젝만 변경할 수 있다. 

복사본을 생성(Instance)하는 Renderer.material

값을 변경을 하지 않아도 Renderer.material을 참조하는 순간!, 사본이 생성된다. 당연히 사본을 생성했기에 배치 랜더링이 되지않는다. 

해결법은 Material Property Block

 

 

학습참고

http://thomasmountainborn.com/2016/05/25/materialpropertyblocks/

https://docs.unity3d.com/kr/530/ScriptReference/MaterialPropertyBlock.html

https://cacodemon.tistory.com/entry/material-%EA%B3%BC-sharedMaterial-%EA%B7%B8%EB%A6%AC%EA%B3%A0-Material-Property-Block

반응형

같은 클래스로 인스턴스를 new로 생성하게 되면  

1번을 제외하고 2~4번은 false

참조형 변수의 주소값을 비교하는 object.ReferenceEquals

즉, 관리 힙에 할당된 객체의 참조 주소 값을 비교해 '같음 여부'를 판단하기 때문에, object.ReferenceEquals '값 형식'의 인스턴스에 사용해서는 안됨

값형식을 넣으면 오류는 안나지만 false를 반환

object.ReferenceEquals의 값을 넣게되면 매개변수타입이 object형식이라 박싱과정이 거친다. 그러면 힙메모리에 값이 할당되게 된다. 결국 스택에 있는 서로다른 주소값이 생기기 떄문에 항상 false를 반환하게된다.

 

 

 

반응형

1. namespace 추가

 

2. EditorWindow상속

monobehavior는 없애주고, start(),update()도 같이 지워준다

 

3. 에디터 이름및 경로 설정

[MenuItem("TestEditor/EditorWindow")]

유니티 에디터의 등록될 이름과 경로를 적어준 뒤 static함수를 하나 만들어주면 아래와 같이 실제 유니티에서 생성된 것을 볼 수 있다.

유니티 에디터

 

4. 에디터 창 띄우기

현재는 클릭해도 아무것도 변화가 없다. 당연!

EditorWindow클래스에있는 GetWindow라는 함수를 사용해 창을 띄울 수 있다.

에디터 창 이름 변경 

아래 My Editor로 변경된 걸 볼 수 있다.

 

5. 글자 띄우기

OnGUI()함수안에 GUILayout.Label("안녕하세요 반갑습니다."); 넣어준다.

 

문자 입력받기

6. 버튼 만들기

GUILayout.Button("버튼")

 

7. 적용

프로젝트 원소 대전에서 플레이 중의 에디터로 속성을 바꿀 수 있게 했다. 속성마다 테스트할 경우가 많기 때문에 만들어봤다.

물일 때는 불속 성이 도망가지만 땅 속성이면 다시 쫒아온다.

물>불>땅>물

반응형

abstract :

상속 제한 : sealed키워드와 반대로 무조건 상속해서 쓰라는 의미 

메서드 오버 라이딩 제한 : 이 메서드는 반드시 오브 라이딩해달라는 의미

 

as :

객체를 캐스팅 할 때 사용되는 연산자로, 캐스팅에 성공하면 캐스트 결과를 리턴하고 실패하면 null을 리턴

 

is :

캐스팅이 가능하면 true, 아니면 false를 리턴

 

base :

해당 키워드를 사용하는 부모 클래스를 가리키는 것

 

const :

상수 필드 또는 지역 상수를 선언할 때 사용한다. 변수가 아니며, 한번 값이 할당되면 이후 변경이 불가능

 

readonly :

성수를 선언할 때 사용, 선언 시 선언할 때 값을 할당하지 않아도 됨, const와 다르게 생성자에서 한번 더 값 변경이 가능하다.

 

continue :

반복문에서 continue키워드 선언 이후 부분은 넘기고 다음 반복문부터 시작하도록 한다.

 

decimal :

고정 소수점 방식이며 연산 속도가 빠르고 수의 정확성이 높은 데신 큰 수를 저장할 때 메모리를 많이 먹게 된다. 16byte

 

double:

부동소수점 방식이며 decimal보다 정확성은 떨어지지만 작은 메모리 공간에 큰 소수를 저장이 가능하다.

 

event :

public이어도 자신이 선언되어 있는 클래스의 외부에서는 호출이 불가능, 객체의 상태 변화나 사건의 발생을 알리는 용도로 사용

 

delegate:

메서드 참조를 포함하고 있는 영역

 

size of :

지정된 형식의 변수에서 사용하는 바이트 수를 반환한다.

 

반응형

에러

훈련을 하기위해 트레이닝 설정값이 있는  yaml확장자인 파일을 불러오는 과정중에 에러가 났다.

 

원인 / 해결방법

yaml은 탭을 허용하지 않는다고 한다. 저거를 탭을 공백을 두지 않고 스페이스바로 공백을 두었더니 해결! 

 

참고

https://github.com/moraes/config/issues/1

반응형

1. 트레이닝 설정값 세팅

config폴더

trainer_config.yaml파일을 복제하고 지금 작업하고 있는 유니티 프로젝트에 넣는다.(#1에서 복사 떴었음)

trainer_config에는 트레이닝에 사용할 여러 가지 설정값들이 존재한다.

2. 트레이닝 설정값 세팅

터미널 창을 열 고을 유니티폴더로 이동 후

mlagents-learn trainer_config.yaml --run-id=firstRun --train --slow 입력 명령어를 입력한다.

유니티 에디터를 실행하라는 명령이 나온다.

 

slow로 명령해 느리지만 자동으로 뭔가 하고 있다. (프로그램이 아무거나 누르는 중이다)

터미널에서 훈련상황 로그를 보여준다.

 

3. 훈련내용 확인

프로젝트 폴더에 가보면 model폴더가 생성된 것을 볼 수 있다. 

 

4. 훈련상황 세팅

파일을 열어주고

 

default선언 부분은 새로 선언한 부분에 없는 속성들은 default에서 속성 값대로 진행된다.

유니티에서 생성한 이름과 같게 Learing_Brain으로 선언한다.

gamma : 낮을수록 먼 미래의 보상을 낮게 평가하기 때문에 즉각적인 보상이 높게 평가됨 / 높으면 미래의 보상을 좀 더 신경 씀

lamda : 낮으면 지금까지의 보상을 기준으로 미래의 보상을 평가함(지금까지의 방향을 유지함) / 높으면 다양성이 커짐 대신 안정성은 떨어짐

buffer_size : 모델이 갱신될 스탭 사이즈

max_steps : 트레이닝을 완전히 종료함

 

훈련을 동시에 실행하기 위해 복사해준다.

Academy TimeScale 변경

TimeScale : 100 -> 15 작을수록 오차가 줄어듦

 

step 5000이 되면 훈련을 종료한다.

 

 

반응형

'유니티 > 머신러닝' 카테고리의 다른 글

ML-Agents) 브레인 생성  (0) 2019.09.17
ML-Agents) 유니티 프로젝트 생성  (0) 2019.09.17
ML-Agents)개발환경 셋팅 (Window)  (0) 2019.09.17

1. Player 브레인 생성

- Player Brain 파라미터 살펴보기

BrainParameters 

Space Size :  관측한 횟수 (Agent 스크립트에서 6번 저장을 하도록 했으니 6으로 설정)

Stacked Vectors : 다양한 관측이 가능 ( 성능이 떨어짐)

Vector Action

Space Type : Continuous로 변경

Space Size : 입력 통로는 2개로 설정했음 (가로, 세로)

- Axis Continuous Player Action설정

사용자가 입력한 방향을 입력받기 위해

- Brain 등록

만든 Brain등록

아카데미가 브레인을 통제하게 됨

 

Player에게도 브레인 등록

테스트 사용자가 키보드로 움직임

 

2 Learning브레인 생성

ML-Agents -> LearningBrain생성

LearningBrain 파라미터 설정

SpaceSize : 6 설정

SpaceType : Continuous

SpaceType : 2 설정

 

Player는 브레인을 playerBrain에서 LearingBrain으로 변경해준다.

이제는 사용자가 아닌 인고 지능 학습활동으로 움직일 것이기 때문에 

 

Academy설정

생성한 Brains 두 개를 등록해준다.

Control : 외부 파이썬 프로그램(텐서 플로우)이 통제할 수 있도록 하는 것 체크해준다.

 

 

반응형

'유니티 > 머신러닝' 카테고리의 다른 글

ML-Agents) 강화학습 #4  (0) 2019.09.17
ML-Agents) 유니티 프로젝트 생성  (0) 2019.09.17
ML-Agents)개발환경 셋팅 (Window)  (0) 2019.09.17

1. Unity프로젝트 생성

 

Unity SDK는 템플릿으로 사용할 수 있는 유니티 프로젝트 폴더이다.

여기에는 유니티 ML-Agent에서 쓰이는 유니티 프로젝트 구성이 모두 들어가 있다. 

템플릿 프로젝트를 훼손하지 않도록 복사해서 사용하는 것이 좋다.

 

그런 다음 유니티로 이 프로젝트를 열어주도록 한다. (2017.04버전 이상이어야 사용 가능)

그러면 ML-Agents라는 폴더가 보인다.

여기 안에는 구동할 수 있는 소스와 사용 예제들이 있다.

2. 아카데미 생성

아카데미는 유니티 외부에 있는 파이썬 프로그램과 유니티 내부에 있는 브레인들을 이어주는 역할을 한다.

 

- 스크립트 생성 / 오브젝트 생성

Player_Academy라는 이름의 스크립트와 Academy라는 오브젝트를 생성해준다.

- 네임스페이스 선언

- Academy 상속

이 Academy는 아카데미에서 동작하기 위한 코드들이 작성돼있다. (Academy는 추상 클래스)

- Academy기능 확인

Max Step : 현재 에피소드를 종료하고 다음 에피소드로 강제로 리셋하는 간격

(0으로 되어있으면 아카데미가 강제로 넘기지 않고 파이썬 프로그램에서 설정한 간격을 따른다.)

Training Configuration : 강화 학습을 시작할 때 사용하는 설정(해상도, 프레임 제한)

Inference Configuration : 이미 강화 학습된 결과를 실시간으로 실행할 때 사용하는 옵션

 

3. 트레이닝 환경 구성

아래 그림과 같이 간단한 훈련을 시키기 위해 세팅을 해준다.

Plane : 보여주기 위한 초록색 땅

Player : 훈련을 시킬 에이전트

Target : Player가 먹을 아이템 (Tag를 goal로 바꿔준다)

DeadZone : 플레이어가 닿으면 죽는 곳

(DeadZone의 Tag는 콜라이더 충돌 시 체크하기 위해 변경해준다)

 

3. Agent스크립트 작성

새로운 스크립트를 만든 후 아카데미와 마찬가지로 네임스페이스 추가와 Agent를 상속받도록 한다.

에이전트 기본 세팅

작성한 Agent스크립트를 Player에 붙이고 Pivot과 Target을 넣어준다.

 

 

학습참고

https://www.youtube.com/watch?v=o8cEK6X8pkM

반응형

'유니티 > 머신러닝' 카테고리의 다른 글

ML-Agents) 강화학습 #4  (0) 2019.09.17
ML-Agents) 브레인 생성  (0) 2019.09.17
ML-Agents)개발환경 셋팅 (Window)  (0) 2019.09.17

 머신러닝

유니티 머신러닝

https://unity3d.com/kr/machine-learning

 

머신러닝은 자율 에이전트에게서 지능형 행동을 끌어낼 수 있는 방식이다.  이 기술로 이용하여 기존의 반복된 작업을 사람이 아닌 컴퓨터가 가능하도록 할 수 있다.

 

유니티 머신러닝의 대한 자세한 설명은 

https://blogs.unity3d.com/kr/2017/09/19/introducing-unity-machine-learning-agents/

 

유니티 머신러닝 에이전트 소개 – Unity Blog

기존에 작성한 두 개의 블로그 게시물에서 게임이 강화 학습 알고리즘 개발을 진전시키는데 수행할 수 있는 역할이 있다고 언급했었습니다. 유니티는 세계에서 가장 널리 사용되는 3D 엔진 개발업체로 머신러닝 및 게임 분야 사이에서 미래를 그려나가고 있습니다. 머신러닝 연구자가 가장 ...

blogs.unity3d.com

 

개발 환경 세팅

 

1. 깃 설치

 

2.  ML-Agents 다운로드 

 

깃에서 주소복사를 해준다

 

3. PowerShell을 이용해서 패키지 Clone

 

복사한 주소를 아래 명령어처럼 입력한다.

설치 중

 

완료되면 설치된 장소로 ml-agents라는 폴더가 생성된다.

4. Ml-agent동작 환경 설정 (Anaconda & Python 설치)

 

- Anaconda 설치 

 

Ml-agent는 Pyhton3.6 버전대에서만 사용이 가능하기에 아나콘다 최신 버전이 아닌 이전 버전을 이용한다.

https://repo.continuum.io/archive/index.html

 

Skip 해준다.

 

- Python개발 환경 설정

 

Anaconda Prompt실행

 

아래 그림처럼 명령어 입력  => 파이썬 3.6 버전을 사용하는 새로운 MI-Agent이름으로 새로운 개발환경을 생성함

 

추가 다운로드할 패키지 명단을 보여줌 (y) 눌러줌

 

ml-agent 개발환경 로드해준다.

 

- ML-Agent 유니티 패키지 개발환경 구성

pip라는 파이썬에 내장되어있는 패키지 매니저를 통해서 유니티 ml-agent가 필요로 하는 외부 의존 라이브러리들을 설치

밑에 그림 명령어를 통해 설치

설치 과정에서 버전에 대한 오류가 났었는데 아래 사이트를 참고하여 해결하였다.

https://github.com/Unity-Technologies/ml-agents/issues/1939

설치확인

mlagents-learn --help  명령어를 통해 설치가 잘되었는지 확인한다.

 

5. 유니티는 Linux Target Support  설치

유니티 허브나 유니티 홈페이지에서 다운로드해준다.

 

 

 

여기까지 개발환경설정이 완료다.

 

 

 

 

 

 

학습 참고 사이트

https://www.youtube.com/watch?v=mJh31T3aGkI

반응형

'유니티 > 머신러닝' 카테고리의 다른 글

ML-Agents) 강화학습 #4  (0) 2019.09.17
ML-Agents) 브레인 생성  (0) 2019.09.17
ML-Agents) 유니티 프로젝트 생성  (0) 2019.09.17

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀 점

 

알고리즘 문제풀이 

문제

최소공배수 : 두 개 이상의 자연수의 공통인 수 중 가장 작은 수
최대공약수 : 두 개 이상의 자연수의 공통인 약수중 가장 큰 수

 

 

 

내 풀이

큰수에서 작은수를 나눈 나머지가 0이 될때 까지 나누면 최소공배수가 된다.

최대 공약수 =  n x m / 최소공배수 공식을 통해 구함

 

작은수를 큰수에 대입, 나머지를 작은수에 대입하여 나머지가 0일 될때가지 나누고 0이 되는 그때의 작은수가 처음 제시된 두의 최대공약수가 된다. -> 유클리드 호제법

 

 

다른 사람 풀이

재귀함수로 b값이 0이 나올때까지 함수를 호출해줬다.  삼항연산자를 통해 조건문없이 원하는 답을 도출 할 수 있었다. 다른 문제를 풀때는 이런 접근방법도 생각해 봐야겠다.

 

 

 

 

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀점

 

알고리즘 문제풀이 

문제

입력된 int [] 형식 배열중에 가장 작은 수를 구해서 제거해주는 과정이 고려해야 할 부분이다. 

 

 

내 풀이

list에 옮겨 담고 각 요소를 비교하며 가장 작은 수를 뺀 리스트를 배열로 변환하여 반환했다.

 

다른 사람 풀이

Linq를 사용하여 배열의 요소들 중 최솟값을 구하고  Where으로 조건을 두어, 아까 구한 최소값을 제외한 요소들로 배열로 만들었다. Linq가 사용은 간편하게 원하는 값을 받아 올 수 있다는 장점이 있지만 속도가 느리다는 점에서 유니티 개발에서는 적절히 사용?을 해야 할 듯싶다.

 

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀 점

 

알고리즘 문제풀이 

문제

고려해야 할 부분은 제곱근만 구하면 되는 문제이다.

 

내 풀이

Math.Sqrt()을 사용해서 입력된 n의 제곱근을 구했다. ath.Sqrt()의 반환 형식은  double형이라 long으로 캐스팅해줬다.

다른 사람 풀이는 접근방식이 같거나 참고할만한 코드가 없어서 이번 문제는 생략했다.

 

+알아두자

Math.Sqrt(Double) Method

지정된 숫자의 제곱근을 반환합니다.

Math.Pow(Double, Double) Method

정된 숫자의 지정된 거듭제곱을 반환합니다.

 

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀 점

 

알고리즘 문제풀이 

문제

long형태로 입력된 숫자를 int형 배열로 반환하는 문제이다.

내 풀이

n을 인덱스로 접근하기 위해 string형태로 변환하고 인덱스를 뒤에서 부터 참조하여 int[] answer에 담았다. 문자열을 인덱스로 접근하면 s[i]는 char형이기 때문에 string으로 바꾸고 다시 int.Parse로 int로 변경해줬다.

 

 

다른 사람 풀이

long형 변수를 2개 선언하여 n의 자릿수로 접근하여 넣어주는 방법이다. while문은 자릿수를 비교했을때 n값을 초과하면 탈출 하도록했다.  

 

 

 

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀점

 

알고리즘문제풀이 

문제

입력된 문자열이 숫자로만 이루어져있는지 체크와 길이가 4또는 6인지 체크해야한다.

내 풀이

삼항연산자를 이용하고 int.TryParse()를 통해 숫자로 변환이 가능한지 체크한다. 

 

다른 사람 풀이

Regex.IsMatch라는  정규표현식을 이용하여 패턴을 검사하여 풀이한 방식

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀 점

 

알고리즘 문제풀이 

문제

입력된 배열의 요소 인덱스를 오름차순으로 정렬하는것은 어렵지 않지만 요소의 인덱스가 가리키는 문자가 중복인 경우가 고려야할 부분이다.  

 

//다른 사람풀이를 2문제를 분석함

다른 사람 풀이 _1

내가 풀려고 했던 접근은 입력된'n' 문자끼리 순서를 비교한 뒤 그 순서대로 정렬을 한다음에 중복된 'n'이 있으면 거기서 또 정렬을 하려고했는데, 이 코드를 보니까 그럴 필요가 없었다. 비교를 해야할 'n'을 맨 앞으로 빼고 그 다음에 정렬하면 된다.  

 

 

 

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀점

 

알고리즘문제풀이 

문제

입력된 long형식을 자릿수 별로 내림차순으로 정렬하는 것이 고려해야 할 부분이다.

 

내 풀이

list를 써서 (배열로 해도 될 듯) int형으로 자릿수 하나하나를 Add 하고, 다시 이중 포문으로 내림차순으로 정렬한다.

 

다른 사람 풀이

String.ToCharArray()로 long형식을 Char배열로 입력하고 입력된 문자를 Sort로 오름차순으로 정렬한 뒤 Reverse로 뒤집는다.  To.CharArray로 

ToInt64(String)

숫자의 지정된 문자열 표현을 해당하는 64비트 부호 있는 정수로 변환합니다.

String.ToCharArray Method

이 인스턴스의 문자를 유니코드 문자 배열에 복사합니다.

 

반응형
 

11047번: 동전 0

첫째 줄에 N과 K가 주어진다. (1 ≤ N ≤ 10, 1 ≤ K ≤ 100,000,000) 둘째 줄부터 N개의 줄에 동전의 가치 Ai가 오름차순으로 주어진다. (1 ≤ Ai ≤ 1,000,000, A1 = 1, i ≥ 2인 경우에 Ai는 Ai-1의 배수)

www.acmicpc.net

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀 점

 

알고리즘문제풀이 

문제

최소의 동전 갯수로  입력된 값을 만드는 문제이다.  가장  큰가치의 돈부터 접근하여 필요한 동전갯수를 증가시키는 방법이 좋을 듯 하다.

 

내 풀이

for문 안에 while문이 없으면 한번만 계산하고 다음 인덱스로 넘어가기 때문에 

(ex 입력된 값 4200원 , coin[i] = 1000 인경우

4200 / 1000 을 4번 해줘야함)

 

 

 

 

반응형

 

 

11399번: ATM

첫째 줄에 사람의 수 N(1 ≤ N ≤ 1,000)이 주어진다. 둘째 줄에는 각 사람이 돈을 인출하는데 걸리는 시간 Pi가 주어진다. (1 ≤ Pi ≤ 1,000)

www.acmicpc.net

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀 점

 

알고리즘문제풀이 

문제

1. 기다리는 사람들의 총 최소시간을 구하기 위한 정렬

2. 각 사람당 몇분이 걸렸는지 계산

 

내 풀이

1. 오름차순으로 정렬하는 것이 가장 최소시간다.

2. 자신의 시간은 전 사람이 기달렸던 시간을 더해주면 기다리는 시간이 나온다.

내가 기다리는 시간 = 전 사람시간 + 내가 뽑는 시간 

 

 

 

 

11399번: ATM

첫째 줄에 사람의 수 N(1 ≤ N ≤ 1,000)이 주어진다. 둘째 줄에는 각 사람이 돈을 인출하는데 걸리는 시간 Pi가 주어진다. (1 ≤ Pi ≤ 1,000)

www.acmicpc.net

 

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀 점

 

알고리즘문제풀이 

문제

입력된 문자열의 알파벳이 +n 했을 경우 'z', 'Z'을 초과했을 경우 다시 'a', 'A'부터 밀려난 값을 구하는 것이 포인트

ex) 알파벳 'y'이고 n 값이 '25'이면 'z'를 초과 하게된다.

 

내 풀이

맨 처음 if(temp == 32)는 공백인 경우의 아무 작업도 하지 않기 위해 넣었음  다른 방법이 있을 것 같은데;;

'a~z', 'A~Z'은 알파벳은 26개이며 입력된 값이 90을 넘을 경우(90('Z') , 122('z')) 다시 알파벳이 시작되는('a', 'A')부터 시작하기 위해 -26을 빼는 과정으로 해결했다. 

 

다른 사람 풀이

'z'와'Z'를 각각 int로 캐스팅한 값을 가지고, if가 공백이 아닌 경우를 체크하고 밑에서 char.IsUpper로 대, 소문자를 체크해주는데 이 과정이  굳이 없어도 될 것 같다. 마지막에는 answer +=을 해주는 게 아닌 string.fomat을 활용해서 채워주고 있다.

위 코드를 활용해서 조건문을 좀 줄여서 다시 작성해봤다.

느낀 점

확실히 같은 문제를 봐도 접근하는 방법이 다르다는 것을 느꼈다. 물론 이 문제 자체가 복잡하지 않아서 크게 벗어나지는 않지만 IsUpper를 이용해서 보이는 코드 길이를 줄일 수 있었다.

 

 

 

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀점

 

알고리즘문제풀이 

문제

배열의 요소중 "Kim"가 몇번째 있는지 구하는 것이 포인트

 

내 풀이

주어진 string[]을 순회하면서 "Kim"을 찾도록했다.

 

다른 사람 풀이

Array.FindIndex()로 특정한 string값을 뽑는 함수를 이용했다.

 

 

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀 점

 

알고리즘문제풀이 

문제

입력된 divisor로 나누었을 때 나머지 값이 0인 element를 구하고 오름차순으로 정렬하는 것이 포인트

 

내 풀이

'%'를 이용해 0이 나오면 나누어 떨어지기 때문에 요소들을 간단히 구할 수 있었다.  

 

다른 사람 풀이

다른 점으로는 divisor이 1 경우  AddRange를 통해 입력받고 있다.

 

느낀 점

문제 자체가 워낙 간단한 문제이고, 리스트와 배열을 정렬하는 함수가 있기 때문에 쉽게 해결할 수 있었다. 

 

 

 

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀점

 

알고리즘문제풀이 

문제

입력된 두 정수중 큰 수와 작은 수를 구하는 과정이 포인트

 

내 풀이

삼항 연산자로 max(큰 수), min(작은 수)를 구하고 for문으로 min이 시작 값 max가 끝 값으로 순회하면서 answer에 더하도록 했다.

 

다른 사람 풀이

큰, 작은 값을 구하지 않고 while문으로 a! = b라는 조건으로 a값을 기준으로

a가 크면 -1, 작으면 +1로 해주고 있다. 이 과정이 a부터 b사이에 값을 더해주는 과정이고 마지막 결괏값을 리턴할 때 b를 더해줌으로써 a와 b까지의 값을 모두 더한 값이 된다. 

 

느낀 점

내가 문제를 보고 포인트라고 생각했던 것은 a가 b 중 누가 더 큰 값인지, 작은 값인지 체크하는 것이었는데, 시작 값이나 끝 값을 미리 정하는 것이 아닌 반복문을 통해 기준으로 잡은 값이 큰 값이면 빼고 작은 값이면 더하는 방식으로 입력받은 두수 사이를 모두 더 할 수 있었다. a!=b인 조건인 두 수가 같을 때 반복문을 빠져나가는 조건은 a값이 b값 바로 전 정수까지 다 다랐다는 말이다. 

 

 

 

반응형

 디자인 패턴 

싱글톤 패턴

같은 인스턴스를 여러 개 만들지 않고, 최초 한번만 메모리를 할당하고 그 메모리에 인스턴스를 만들어서 사용하는 패턴이다. 어디서든지 접근하기 쉽다.

 

구현방법

가장 기본적인 싱글턴 구현 방법이다. 인스턴스를 요청하기 전까지는 객체를 생성하지 않는다.

늦은 초기화(Lazy initialization) : 멀티스레드 환경에서는 동시에 Instance을 호출하게 되면 둘 이상 객체가 만들어질 위험이 있다.

 

정적 초기화

이른 초기화(Eager initialization) 

로딩 때 생성되므로 스레딩에 안전한 대신 미리 생성하므로 안 쓰는 경우에 메모리 낭비가 될 수 있음

 

멀티스레드에서 교착상태를 피하기 위한 싱글턴

교착상태를 피하기 위해 이중 검사 잠금

lock키워드 설명 : http://www.csharpstudy.com/Threads/lock.aspx

 

싱글턴 문제점

개방 폐쇄 원칙(OCP)을 위배될 수 있다. (객체 지향 설계 원칙)

커플링이 심해질 수 있음 => 한 곳에서 변경이 다른 부분에 영향을 미치게 될 확률이 커짐

 

학습 참고 사이트

 

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀점

문제


우선 문제를 봤을 때 고려할 부분으로는

입력된 string의 길이가 짝수인지 홀수인지 체크해주고 중간값을 반환하는 부분이다. 

 

 

내 풀이


2로 나눈 나머지값으로 짝/홀을 확인한다. 문제도 그렇고 어렵지 않은 내용인듯 하다.

 

다른 사람의 풀이


일단 짝/홀을 비교하는 조건문이 없다.   Substring(시작인덱스,시작인덱스로부터 몇번까지)으로  반환하고있다. 

 

반응형

파란색 : 풀면서 어려웠던 부분 or 고려해야 될 부분

빨간색 : 해결방법

초록색 : 느낀점

문제


우선 문제를 봤을 때 고려할 부분으로는

첫 번째로, 여벌은 1개이기에 중복적으로 빌려줄 수 없도록 해야한다.

두 번쨰로는 잃어버린 학생과 여벌로 가져온 학생이 같을 수 있다. (당연히 여벌은 1개라 빌려줄 수 없다.)

 

 

내 풀이


잃어버린 학생배열과 여벌을 가져온 학생배열을 list로 옮긴 후 두 배열을 비교하여 중복된 값을 구한다.(두 번째 고려사항)

마지막 foreach문에서 빌려줄수있는 학생배열을 순회하면서 빌려준 학생은 다시 빌릴 수 없도록 삭제시켜주고 있다.(첫 번째 고려사항) 

 

 

다른 사람의 풀이


우선 차이점으로 중복된 값을 걸러내기위한 반복문을 사용하지않고 Linq기능을 사용하여 lost, reserve배열 서로 중복되지 않는 값만 입력받았도록 하고있다.

Linq기능을 사용하면 간결하고 연산 횟수가 줄지만, 가비지가 생성하기에 게임을 개발에 사용하기에는 적절하지 않다.   

 

반응형

제어구조


if

String.valid? string인지 체크

 


unless

is_intege 숫자인지 체크

 


case

여러 패턴에 대해 매치해야 한다면 case를 이용

일치하는 패턴이 없는 경우 에러발생

'_'는 "그 외의 모든 것"에 매치되는 else처럼 생각하면 된다. (case구문에서 '_'이 없다면 일치하는 패턴이 없을 때 오류 발생)

 

'_'사용

 

case는 패턴 매칭에 의존하기 때문에 같은 규칙과 제약이 모두 적용된다. 기존의 변수에 매치하고자 한다면 핀연산자를 사용해야한다.

 

when으로 점검기능이있다. x > 0 크면 "Will match"

 


Cond

값이 아닌 조건식에 매치해야 할 때 사용 (else if 기능)

Cond문 마찬가지로 예외처리가 없으면 에러를 발생하는데, true조건식으로 처리해준다.

 


with

중첩된 case구문이 쓰일만한 곳이나 깔끔하게 파이프 연산을 할 수 없는 상황에서 유용하다.

'<-'은 오른쪽을 왼쪽과 비교하기 위해 패턴매칭을 사용

매치 실패한 경우

 

반응형

'프로그래밍언어 > Elixir' 카테고리의 다른 글

Elixir) 예제 연습_패턴 매칭  (0) 2019.08.22
(Elixir)로 JSON API 서버 만들기  (0) 2019.08.21
Elixir) 예제 연습 Enum  (0) 2019.08.21

+ Recent posts