728x90

기본적인 포인터 개념은 생략.

 

 

1.

문자열은 cosnt 영역에 생성되므로 문자열을 받는 변수도 const 타입이여야 한다.

2.

문자열 마지막에는 NULL이 포함되어 문자개수+1만큼의 char배열이다.

 

3.

포인터 변수지만 문자열 포인터 변수는 cout-endl에 value가 찍힌다.

가장 혼란스럽게 한부분이다. cout-endl 내부원리를 알아야 정확히 이해하겠지만

추론하기로는 char* 변수는 cout-endl에서 null 문자를 메모리에서 읽을까지 값을 출력한다.

보통은 char*변수에 문자열을 담기 때문인것 같다.

덕분에 char*에 char형 데이터를 넣게되면 null 포인트를 찾지 못하고 외계어가 출력된다.

 

그렇다면 문자열 주소를 출력하려면 &dd?

 

그럼 dd 도 이미지 주소를 가리키므로 주소의 주소를 출력하게된다. 실제 dd가 가리키는 주소와 출력된 주소가 다른걸 확인할 수 있다.

 

4.

문자열 포인터값은 문자열 가장 첫인덱스 주소값을 나타낸다.

그럼 주소값++ 이런식으로 다음 인덱스에 접근해서 문자를 바꿀수 있나?

없다. 애초에 문자열은 const 따라서 포인터변수도 const 따라서 변경 불가.

 

5.

꿀팁.

디버깅 중에

위와 같이 메모리 창을 띄워놓으면

내부적으로 메모리야 어떻게 쓰이고 어떤값이 들어갔는지 확인할 수 있다!

이걸 모르고 console에 찍히는 값만 보고 추론하면 답이 없다.. ㅜ

728x90
728x90

매번 반복되는 코드 치기 귀찮아서

방법을 찾다가

처음에는 확장 기능

intellsense(기본 내장), visual assiste 등 찾다가

 

코드 조각 관리자

코드 조각 관리자로 원하는 shortcut 명령어를 snippet 파일로 커스텀할 수 있길래 트라이! 해봄

커스텀 방법은!

https://docs.microsoft.com/ko-kr/visualstudio/ide/walkthrough-creating-a-code-snippet?view=vs-2019

공식 api 문서에 아주~ 잘 나와 있음

 

하하하

 

적용모습

 

Visual studio 2019 IDE -도구 - 코드조각관리자

 

 

728x90
728x90

Point-Point

 그림

LinearBezier

그림

LinearBezier-LinearBezier

그림

QuadraticBezier

그림

Quadratic-Quadratic

그림

CubicBezier

그림

728x90

'수학과물리' 카테고리의 다른 글

Combination,조합  (0) 2021.08.22
Log  (0) 2021.08.13
728x90

https://youtu.be/aEar_3UB65M

데이터를 공유 사용하여 메모리를 절약하는 패턴

일반적으로 공통으로 사용되는 객체는 새로 생성하지 않고 공유하여 자원을 활용

 

C#(https://ko.wikipedia.org/wiki/%ED%94%8C%EB%9D%BC%EC%9D%B4%EC%9B%A8%EC%9D%B4%ED%8A%B8_%ED%8C%A8%ED%84%B4)

using System.Collections;
using System.Collections.Generic;
using System;

class GraphicChar {
    char c;
    string fontFace;
    public GraphicChar(char c, string fontFace) { this.c = c; this.fontFace = fontFace; }
    public static void printAtPosition(GraphicChar c, int x, int y)   {
        Console.WriteLine("Printing '{0}' in '{1}' at position {2}:{3}.", c.c, c.fontFace, x, y);
    }
}

class GraphicCharFactory {
    Hashtable pool = new Hashtable(); // the Flyweights

    public int getNum() { return pool.Count; }

    public GraphicChar get(char c, string fontFace) {
        GraphicChar gc;
        string key = c.ToString() + fontFace;
        gc = pool[key] as GraphicChar;
        if (gc == null) {
            gc = new GraphicChar(c, fontFace);
            pool.Add(key, gc);
        }
        return gc;
    }
}

class FlyWeightExample {
    public static void Main(string[] args) {
        GraphicCharFactory cf = new GraphicCharFactory();

        // Compose the text by storing the characters as objects.
        List<GraphicChar> text = new List<GraphicChar>();
        text.Add(cf.get('H', "Arial"));    // 'H' and "Arial" are called intrinsic information
        text.Add(cf.get('e', "Arial"));    // because it is stored in the object itself.
        text.Add(cf.get('l', "Arial"));
        text.Add(cf.get('l', "Arial"));
        text.Add(cf.get('o', "Times"));

        // See how the Flyweight approach is beginning to save space:
        Console.WriteLine("CharFactory created only {0} objects for {1} characters.", cf.getNum(), text.Count);

        int x=0, y=0;
        foreach (GraphicChar c in text) {             // Passing position as extrinsic information to the objects,
            GraphicChar.printAtPosition(c, x++, y);   // as a top-left 'A' is not different from a top-right one.
        }
    }
}

 

여러 오브젝트에 의해 다양한 데이터가 필요로 하고, 그 데이터는 중복되기도 한다면

flyweight 패턴으로 중복을 없애고 재사용하므로써 메모리를 절약하고 데이터 코드 수정을 일괄적으로 할 수 있다.

 

그런데 게임에서 실제로 어느 상황에서 쓰일까??

기본적인 속성테이블들은 고유 인덱스를 가지고 있고

row가 100개면 인덱스도 100개라서 번거롭게 flyweight패턴 쓸일이 없고.. 그냥 dic이나 hash에 그대로  for문 돌려서 넣어 버리면 되는데...

 

중복 row가 있는 테이블을 읽어서 메모리에 할당 해놓을떄 유용할텐데... 

 

 

728x90

'Skills > DesignPattern' 카테고리의 다른 글

[DesignPattern]Template  (0) 2020.03.14
728x90

문제

 We * love = CodelQ

 W = 7 e =4 l =3 o = 8 v =0 C =2 d =1 l =9 Q =6

 74*3804=281496

 

다음 식을 만족하는 숫자 대입 방법은 몇 가지 있는지 구해 보세요. (단 최상위 문자에 0은 들어가지 않고 다른 문자에는 다른 숫자가 대입됩니다)

 

READ + WRITE + TALK = SKILL

 

난이도

IQ 80

 

목표시간

20분

 

풀이(c#,VS)

1. 

-

 

문제정답(사용언어:python)

 

1.

  r e a d
w r i t e
  t a l k
s k i l l
w+1=s or w+2=s   e+a=8 or e+a=9 or e+a=10 a+t=8 or a+t=9 or a+t=10

(d+e+k)%10 = l

((a+t+l)*10+d+e+k)%100 = l*11

#풀이1
from itertools import permutations

count =0;
for (r,e,a,d,w,i,t,l,k,s) in permutations(range(10)):
    if r==0 or w==0 or t==0 or s==0:
        continue

    read = r*1000 + e*100 + a*10 +d
    write = w*10000 + r*1000 +i*100 + t*10 + e
    talk = t*1000 + a*100 + l*10 + k
    skill = s*10000 + k*1000 +i*100 + l*10 + l
    if read+write+talk==skill:
        count +=1

print(count)

#풀이2    디버깅이 안된다.. 예제 소스(책 소스랑 좀 다르다) 찾아서 받아서 돌려봤는대도 안된다..
import re
from itertools import permutations
from collections import OrderedDict

count =0

for(e,a,d,t,k,l) in permutations(range(0,10),6):
    if ((a+t==8) or (a+t==9) or (a+t==10)) and\
       ((a+e==8) or (a+e==9) or (a+e==10)) and\
       ((d+e+k)%10==1) and\
       (((a+t+l)*10+d+e+k)%100==l*11):
       
        temp = [item for item in range(0,10) if item not in [k,e,d,l,t,a]]
        for(i,r,s,w) in permutations(temp,4):
            if((r!=0) and (w!=0) and (t!=0)) and\
                ((s==w+1)or(s==w+2)):
                   
                    read = r*1000 + e*100 + a*10 +d
                    write = w*10000 + r*1000 +i*100 + t*10 + e
                    talk = t*1000 + a*100 + l*10 + k
                    skill = s*10000 + k*1000 +i*100 + l*10 + l
                    print("{}+{}+{}={}".format(read,write,talk,skill))
                    if read+write+talk==skill:
                        print("d{}+{}+{}={}".format(read,write,talk,skill))
                        count +=1

print(count)

 

책 제목 그대로... 코딩 퍼즐? 같은 느낌이다.. 쓰기 위한 코드? 알고리즘이라기 보단 다양한 방법으로 끼워 맞추는 놀이같은 문제다.. ㅜㅜ...

 

 

728x90
728x90

포인터란?

메모리 주소를 가르킨다.

 

포인터변수란

메모리 주소를 갖고 있는 변수

 

포인터 변수 선언

int* pointer

int형 변수 메모리 주소를 가르킨다

ex)

int num =4;

int* pointer = &num;

 

&란?

변수의 주소값을 반환한다.

포인터 변수에는 주소값만 할당 가능하므로

int num =4;

int* pointer = &num;

와 같이 사용한다

 

*란?

&기호가 변수의 주소값을 반환한다면

반대로 *는 포인터변수가 가리키는 실제 값을 반환한다

ex)

int* pointer;

pointer // address

*pointer // value 

 

포인터 증감 +,-

int* pointer;

pointer++; ???

포인터가 가리키는 주소값의 다음 주소값을 가리킨다

주의할것은 기존에 포인터가 0을 가리킨다면 +1 증가시켰을떄

1이 아닌 4를 가리킨다.

포인터변수 타입이 int형이고 int형은 4바이트 이기 때문에 

int형의 다음 값을 가리키는 주소값은 4바이트 차이가 나는 주소값이된다.

 

 

728x90
728x90

포큐아카데미 c++3200강의 내용을 개인학습용으로 정리한 내용입니다.

 

c와는 달리 모든 입력이 stream 형태로 들어온다.

 

>>

출력연산자? (정식명칭)extraction 연산자? 뽑아오는 연산자?

 

C의 scanf()는 위험하다?

C의 scanf()는 경계검사를 하지 않기 때문에 위험하다.

보통 C에 입력된 데이터의 끝을 알기위해 뒤에 경계문자를 넣기 떄문에

사용자가 미리 경계의 끝을 알고 메모리를 할당하지 않으면 문제가 생긴다

 

C++의 cin은 안전한가?

C의 scanf와 마찬가지로 입력시 할당한 char[]의 길이를 알지 못하기 때문에

같은 문제가 발생한다.

 

scanf() cin 안전하게 사용하는 예

 

여러개 입력

scanf() cin 모두 공백으로 구분 가능하다

 

입력 스트림 상태

아래 그림 -표 두번째 처럼 콘솔 입력과 텍스트를 읽어와 입력처리하는 경우

다른 스트림상태가 나올수 있다.

콘솔 입력은 마지막에 엔터를 치기 떄문에...

입력버리기

cin.clear()

cin.ignore()

get()

getline()

 

 

 

 

 

728x90
728x90

포큐아카데미 c++3200강의 내용을 개인학습용으로 정리한 내용입니다.

 

namespace

자바의 package C#의 namespace와 유사하다.

같은 이름의 클래스나 함수를 namespace로 구분하여 묶을 수 있다.

 

pragma

https://docs.microsoft.com/ko-kr/cpp/preprocessor/pragma-directives-and-the-pragma-keyword?view=vs-2019

컴파일 기능을 지정한다.

#pragma,_pragma 키워드로 사용가능하다.

차이점은 _pragma는 인라인에서 사용가능하다.

(#pragma의 경우 #을 문자열화 연산자로 인식하기 때문에)

ex) #pragma once   중복 include 되는 header를 방지한다. pragma 로 지정하기 전에는 하나하나 header 중복 include 체크를 했다고 한다...

 

<<

insertion 연산자? push 연산자? 밀어 넣는 연산자?

정식 명칭은 insertion 연산자라고 하지만 정식 명칭을 잘 쓰진 않는것 같다.

기본적으로 쉬프트 연산자지만 출력할때 재정의 되어 insertion 연산자의 기능을 하는것 같다.

참고로 +,-와 같은 연산자도 다른 동작이 하도록 재정의 가능하다.

 

manipulator(조정자)

 

위 조정자는 cout을 사용하기 위한 include를 하게되면 사용가능하나

아래 조정자는 별도의 iomanip를 include해야 사용가능하다

특이점은 함수처럼 매개변수를 사용한다

size_t

보통 문자열,메모리의 크기등 양수값을 표현할떄 쓰는 자료형? 이다

unsigned int 와 비슷하다.

http://mwultong.blogspot.com/2007/06/c-sizet-unsigned-int.html

 

C언어] size_t 형의 의미; unsigned int와 차이점, 차이

size_t 는 unsigned int 이며, 문자열이나 메모리의 사이즈를 나타낼 때 사용합니다. "unsigned int"를 typedef unsigned int size_t; 이렇게 size_t 라는 이름으로 정의해 놓은 것입니다. size_t 는, 32비트 운영체제에서는 "부호없는 32비트 정수"이고, 64비트 운영체제에서는 "부호없는 64비트 정수"입니다. 그러나 "unsigned int" 또는 "int"는, 64비트 OS라고 해서 꼭 64비트 정

mwultong.blogspot.com

cout 멤버메서드

조정자 대신 cout 멤버메서드

네임스페이스는 ios_base.

그리 많이 사용하지 않는 방법이다.

 

 

 

 

728x90
728x90

출처

https://m.blog.naver.com/PostView.nhn?blogId=ysw1130&logNo=220339033018&proxyReferer=https%3A%2F%2Fwww.google.com%2F

 

FTP

 File Transfer Protocol로 인터넷상에서 컴퓨터 사이의 파일을 전달하는 데 사용되는 프로토콜

 

TFTP (Trivial 하찮은)

 Trivial File Transfer Protocol로 FTP와 마찬가지로 파일을 전송하기 위한 프로토콜이지만 FTP보다 더 단순한 방식으로 파일 전송.

 

FTP TFTP
TCP기반 UDP기반
20,21번 Port 사용 69번 사용
로그인 절차가 있다. 로그인 절차가 없다.
파일 디렉토리 볼 수 있다.(DIR) 파일 디렉토리를 볼 수 없다.
728x90
728x90

문제

 제곱근을 소수로 나타내었을 때 0~9의 모든 숫자가 가장 빨리 나타나는 최소 정수를 구하시오. 단, 여기서는 양의 제곱근만을 대상으로 합니다. 정수 부분을 포함하는 경우와 소수 부분만 취하는 경우 각각에 대해 모두 구하시오.

 

난이도

IQ 85

 

목표시간

20분

 

풀이(c#,VS)

1. 

using System;
using System.Linq;

namespace _12_SquareRoot
{
    class Program
    {
        static void Main(string[] args)
        {

            //정수포함           
            int targetNum = 2;
            while (true)
            {
                string sTargetNum = Math.Sqrt(targetNum).ToString().Replace(".", "");
                Console.Write(targetNum + "/" + Math.Sqrt(targetNum) + "/" + sTargetNum);
                if (StringDuplicationDelete(sTargetNum).Length == 10)
                {
                    Console.WriteLine(targetNum);
                    break;
                }
                targetNum++;
            }

            //소수포함           
            //int targetNum = 2;
            //while (true)
            //{
            //    string sTargetNum = string.Empty;
            //    try
            //    {
            //        sTargetNum = Math.Sqrt(targetNum).ToString().Split('.')[1];
            //        Console.Write(targetNum +"/" + Math.Sqrt(targetNum) + "/"+ sTargetNum);
            //    }
            //    catch
            //    {
            //        //split 에러
            //    }

            //    if (StringDuplicationDelete(sTargetNum).Length == 10)
            //    {
            //        Console.WriteLine(targetNum);
            //        break;
            //    }
            //    targetNum++;
            //}
        }

        public static string StringDuplicationDelete(string target)
        {
            string newString = string.Empty;

            for (int i=0; i< target.Length; i++)
            {
                if (!newString.Contains(target[i]))
                {
                    newString += target[i];
                }
               
            }

            Console.WriteLine(" /  " + newString);
            return newString;
        }
    }
}

 

문제정답(사용언어:python)

 

1.

from math import sqrt

# 정수 부분을 포함하는 경우
i =1
while True:
     i +=1
     # 소수점을 제거하고 왼쪽 10문자 추출
     string = '{:10.10f}'.format(sqrt(i)).replace('.','')[0:10]
     # 중복을 제거해서 10문자라면 종료
     if len(set(string)) == 10 :   
         break

print(i)

# 소수 부분만 계산하는 경우
i =1
while True:
     i +=1
     # 소수점을 분할하여 소수 부분만을 취득
     string = '{:10.10f}'.format(sqrt(i)).split('.')[1]
     # 중복을 제거해서 10문자라면 종료
     if len(set(string)) == 10 :
         break

print(i)

 

-

 

 

728x90
728x90

문제

 피보나치 수열 중 각 자리의 숫자를 더한 수로 나누어 떨어지는 수를 다음 예에 이어 작은 쪽부터 5개 구해보세요.

 예)

   2 > 2/2

   3 > 3/3

   5 > 5/5

   8 > 8/8

   13 > 13/4  x

   21 > 21/3

   144 > 144/9

 

난이도

IQ 85

 

목표시간

20분

 

풀이(c#,VS)

1. 

using System;

namespace _11_Fibonacci
{
    class Program
    {
        static void Main(string[] args)
        {
            long num1 = 1;
            long num2 = 2;
            for(long i =0; i<1000; i++)
            {
                //피보나치 수 구하기
                long pbNum;
                pbNum = num1 + num2;

                num1 = num2;
                num2 = pbNum;

                //자릿수 구하기
                long tempPbNum = pbNum;
                long sumNumLen = 0;
                do
                {
                    sumNumLen+= (long)(tempPbNum % 10);
                    tempPbNum = (long)(tempPbNum / 10);
                } while (tempPbNum > 0);
                   
                //자릿수 합으로 나누었을때 떨어지는 숫자 구하기
                if(pbNum%sumNumLen == 0f)
                {
                    Console.WriteLine(pbNum + "/" + sumNumLen);
                }

                
            }
        }
    }
}

 

문제정답(사용언어:python)

 

1.

a=b=1
count = 0
while count<11:
    c = a+b
    # 1자리씩으로 분할하여 각 자리의 합을 취득
    sum =0
    for e in str(c):
        sum +=int(e)
    if c%sum == 0:
        #나누어 떨어지면 출력
        print(c)
        count += 1
    a,b,=b,c

 

-

재귀를 이용해서 문제를 풀지 않았지만 책에서는 재귀를 이용하면 자칫 stackoverflow에 빠질 수 있다고 한다. 재귀가 끝나는 시점까지 호출 메소드관련 메모리가 스택에 계속 살아 있어야 되기 때문인것 같다. 간단하고 작은 수를 다룰 때는 재귀 나름의 장점이 있지면 역시 재귀는 쓰기전에 고려해볼 점이 많은것 같다.

 

728x90
728x90

문제

 남자 20명, 여자 10명이 도착하였을 때 어디에서 끊더라도 두 그룹 모두 남자와 여자의 수가 달라지게 되는 도착 순서가 몇 가지 있는지 구해 보세요.

 

난이도

IQ 80

 

목표시간

20분

 

풀이(c#,VS)

1. 재귀를 이용하여 풀이

        -       도착  
      -         - 도착
    -         -    
  -         -      
          -        

남성 10, 여성 5명, 남성 가로축, 여성 세로축 이라고 가정 했을때  - 부분을 지나지 않고 도착 경로에 도착할 수 있는 가짓수를 찾으면 된다.

/*
20200204
ksj
*/ 
using System;

namespace _9_MaleFemaleUnBalance
{
    class Program
    {
        static void Main(string[] args)
        {
            int cnt = 0;
            Move(1, 0, 0, ref cnt);
            //처음 위칸으로 이동하면 (여자가 먼저 도착하면) 절대로 타겟 경로로 이동할 수없다.
            //Move(-1, 0, 0, ref cnt);   // 이때 cnt는 0이다.

            Console.WriteLine(cnt);
        }

        static void Move(int dir, int x, int y, ref int cnt)
        {
            //dir  1 오른쪽한칸 x++
            //dir  -1 위쪽한칸 y++
            if (dir == 1)
            {
                x++;
            }
            else
            {
                y++;
            }
                        
            if ((x == y) ||( (x-10) == y) || x > 20 || y > 10)  //범위 벗어나거나 여자 남자 수가 같아지는 지점
            {
                return;
            }
            else if ((x == 19 && y == 10) || (x == 20 && y == 9)) //도착지
            {
                cnt++;               
            }
            else //새로운 이동 (위,아래)(여자,남자)
            {
                Move(1, x, y,ref cnt);
                Move(-1, x, y,ref cnt);
            }
        }
    }
}

 

문제정답(사용언어:python)

1. 최단 경로 문제

4 10 20 35
3 6 10 15
2 3 4 5

죄측 아래에서 우측 위 꼭지점 까지 가는 총 가짓수는 35가지이다.

해당 점까지 이동할때 이전 두점의 가짓수를 더한 값과 같다.

 

2. 2차원 배열을 1차원으로 표현함

boy, girl = 20, 10
boy, girl = boy+1, girl+1

arr = [0] * (boy*girl)
arr[0] = 1

#2차원 배열 형태를 arr[가로현재위치 + 가로최대크기 * 세로현재 위치]와 같이 1차원 형태로 표현 했다.
for g in range(0,girl):
    for b in range(0,boy):
        if(b!=g) and (boy-b != girl - g):
            if b>0:
                arr[b+boy*g] += arr[b-1+boy*g]
            if g>0:
                arr[b+boy*g] += arr[b+boy*(g-1)]

#-2 인덱스는 마지막 인덱스에서 가로로 -2칸이동을 의미
#-boy- 인덱스는 마지막 인덱스에서 가로 한줄 내려가고 가로로 -1칸 이동을 의미
print(arr[-2] + arr[-boy-1])

 

-

 

728x90
728x90

문제

 전후 좌우로 움직이는 로봇 청소기가 있다. 또한 같은 장소를 다시 지나다지니 않는다. 이때 이 로봇이 12회 이동할 때, 생각할 수 있는 이동 경로의 패턴이 몇 가지인지 구해 보세요.

 

난이도

IQ 80

 

목표시간

20분

 

풀이(c#,VS)

1.

 

/**
 2020.01.31
 ksj

 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _8_SmartRobotCleaner
{
    class Program
    {
        static int MAXK_COUNT = 12;
        static int[,] dirArr = new int[4,2]{ { 0, 1 }, { 0, -1 }, { 1, 0 }, { -1, 0 } };
        static int dd = 0;
        static void Main(string[] args)
        {
            List<int[]> log = new List<int[]>();

            //초기좌표 0,0
            int[] initPos = new int[2]{ 0, 0 };
            log.Add(initPos);

            Console.WriteLine(Move(log));
        }

        static int Move(List<int[]> log)
        {
            if( log.Count == MAXK_COUNT+1)
                return 1;

            int cnt = 0;

            for (int i = 0; i < dirArr.GetLength(0); i++)
            {
                //next move pos
                int[] nextPos = new int[2] { log[log.Count - 1][0] + dirArr[i, 0], log[log.Count - 1][1] + dirArr[i, 1] };

                //can move?
                bool canMove = true;
                for (int j = 0; j < log.Count; j++)
                {
                    if (log[j][0] == nextPos[0] && log[j][1] == nextPos[1])
                    {
                        canMove = false;
                        break;
                    }
                }

                if (canMove)
                {
                    log.Add(nextPos);
                    cnt += Move(log);
                }
            }
            return cnt;
        }
    }
}

 

문제정답(사용언어:python)

1. 깊이 우선 탐색

2. 배열 -1 인덱스는 배열 맨 마지막 인덱스를 뜻함

N = 12

def move(log):

    # 맨 처음 위치를 포함하여 N+1개 조사하면 종료
    if len(log) == N+1:
        return 1

    cnt =0
    #전후 좌우 이동
    for d in [[0,1],[0,-1],[1,0],[-1,0]]:

        # 탐색이 끝나지 않았으면 이동시킴
        next_pos = [log[-1][0] + d[0], log[-1][1] + d[1]]
        print(log, d, next_pos)
        #로그에 다음 위치가 기록되어 있는지 확인하기
        check = False
        for p in log:
            if p[0] == next_pos[0] and p[1] == next_pos[1]:
                check = True # 있는 경우 플래그를  True로 변경
        if check == False:
            cnt += move(log + [next_pos])

    return cnt

print(move([[0,0]]))

 

배운점

c#코드가 stackoverflow가 발생한다.. 로그를 배열이 아닌 리스트로 담고 있는 차이인데.. vs 스택사이즈 설정을 확인하려고 속성창에 들어가는데;; 안 보인다... 프로젝트 생성할떄 잘못된건지.. 버전문제인지 잘 모르겠다. 보면 볼수록 파이썬이 코드가 직관적이고 유연성이 좋아보인다.. 컬렉션 추가도 간단한 연산처리 처럼 되니.. 파이썬하다가 불편해서 다른 언어 쓰겠나..

728x90
728x90

---

728x90
728x90

문제

 연월일을 YYYYMMDD의 8자리 정수로 나타내었을 때 2진수로 변환하여 거꾸로 나열한 다음 다시 10진수로 되돌렸을 때 원래 날짜와 같은 날짜가 되는 것을 찾아보세요. 기간은 지난 도쿄 올림픽(1964년 10월 10일)부터 다음 도쿄 올림픽(2020년 7월 24일 예정)으로 하겠습니다.

 

ex)

 1. YYYYMMDD의 포맷 -> 19660713

 2. 2진수로 변환 -> 1001010111111111110101001

 3. 2진수를 거꾸로 나열 -> 1001010111111111110101001

 4. 거꾸로 나열한 2진수를 10진수로 되돌림 -> 19660713

 

난이도

IQ 80

 

목표시간

20분

 

풀이(c#,VS)

1.진수변환,문자열Reverse

2.DateTime 생성자 에러로 날짜변환 가능여부 판단

/*
* 2020.01.30
* ksj
*/ 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _6_BinaryConversionOfDates
{
    class Program
    {
        static void Main(string[] args)
        {
            int start = 19641010;
            int end = 20200724;

            for (int i = start; i <= end; i++)
            {
                string binarayNum = Convert.ToString(i, 2);
                string ReverseNum = new string(binarayNum.ToCharArray().Reverse().ToArray());

                if (binarayNum.Equals(ReverseNum))
                {
                    try
                    {
                        string decimalNum = Convert.ToInt32(binarayNum, 2).ToString();
                        new DateTime(Convert.ToInt32(decimalNum.Substring(0, 4)), Convert.ToInt32(decimalNum.Substring(4, 2)), Convert.ToInt32(decimalNum.Substring(6, 2)));

                        Console.WriteLine(decimalNum);
                    }
                    catch
                    {
                        //날짜 형식 변화 불가
                    }
                    
                }

            }
        }


    }
}

 

문제정답(사용언어:python)

1.탐색 범위를 확인한다.

 19641010 : 1001010111011001010110010

 20200724 : 1001101000011110100010100

2. 25자리이며 앞자리가 1001로 공통이다.

3. 이진수를 reverse했을 일치해야하므로 

4. 탐색범위는 1001 ******** * ******** 1001 과 같은 형태다

5. 5~12자리 수와 14~21자리 수 역시 대칭되어야 하므로 일치된다.

6. 따라서 5~12자리수만 탐색 하면된다.

# 날짜를 다루는 datetime 클래스 불러오기
from datetime import datetime, timedelta

# 대상 기간에서 2진수의 5번째 문자부터 8개의 문자 추출
from_left = int(bin(19641010).replace("0b","")[4:4 +8],2)
to_left = int(bin(20200724).replace("0b","")[4:4 +8],2)

# 좌우의 8문자를 반복
for i in range(from_left, to_left+1):
    l = "{0:08b}".format(i)     # 왼쪽
    r = l[::-1]
    for m in range(0, 1+1):
        value = "1001{}{}{}1001".format(l, m, r)
        try:
            # 변환 가능한지 확인
            date = datetime.strptime(str(int(value,2)), "%Y%m%d")
            # 변환 가능할 경우 출력
            print(date.strftime("%Y-%m-%d"))
        except:
            # 변환 불가
            pass

    

 

배운점

 날짜형식인지 여부를 datetime api 에러로 쉽게 확인.

 탐색 범위를 연구하여 규칙성을 찾고 탐색 범위를 줄임.

 단, 제시된 조건에서만 적용되는 규칙성이기 때문에 확장성이 없고 규칙성을 이해하고 있는 사람이 아니라면 소스코드만 보고 문제를 이해하기 힘들다. 

728x90
728x90

문제

 수학의 미해결 문제중 하나로 콜라츠 추측이 있다.

 

 콜라츠 추측

   -n이 짝수인 경우, n을 2로 나눈다.

   -n이 홀수인 경우, n에 3을 곱해 1을 더한다.

  이 계산을 반복하면 초깃값이 어떤 수였더라도 반드시 1에 도달한다.

 

이 내용을 조금 바꾸어 초깃값이 짝수면 맨 처음에만 n에 3을 곱하여 1을 더하는 것에서 시작하기로 하고 '맨 처음의 수'로 돌아가는 법을 생각해 보자.

ex)

 2 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2

 4 13 40 20 10 5 16 8 4

 6 ....(6으로 돌아가지 않음)

 

10000 이하의 짝수 중 앞의 2나 4와 같이 '처음의 수로 돌아가는 수'가 몇 개 있는지 구해 보세요.

 

난이도

IQ 75

 

목표시간

15분

 

풀이(c#,VS)

1.재귀함수를 이용

2.초기값이 어떤 수더라도 반드시 1에 도달하다는 점

/*
 *2020.01.28
 * ksj
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _6_CollatzConjecture
{
    class Program
    {
        static void Main(string[] args)
        {
            int count = 0;

            for(int i=2; i<=10000; i += 2) //10000이하의 짝수 갯수만큼 반복
            {
                int num = i * 3 + 1;

                if (cal(i,num))
                {
                    count++;
                }
            }

            Console.WriteLine(count);
        }

        private static bool cal(int originalNum, int curNum)
        {
            if(originalNum == curNum)
            {
                return true;
            }

            if(curNum == 1)
            {
                return false;
            }

            if (curNum % 2 == 0)
            {
                int temp = curNum / 2;
                return cal(originalNum, temp);
            }
            else
            {
                int tmep = curNum * 3 + 1;
                return cal(originalNum, tmep);
            }
        }
    }
}

 

문제정답(사용언어:python)

1.초기값이 어떤 수더라도 반드시 1에 도달하다는 점

# 반복하며 확인
def is_loop(n):
    # 맨 처음에는 3을 곱하고 1을 더함
    check = n*3+1
    # 1이 될 때까지 숫자를 변화시키는 작업 반복
    while check !=1:
        check = check // 2 if check % 2 == 0 else check * 3 +1
        if check == n:
            return True
        
    return False

# 2~10000 범위의 짝수 확인하기
cnt = 0
for i in range(2, 10000+1,2):
    if is_loop(i):
        cnt+=1
print(cnt)

 

728x90
728x90

문제

환전 자판기가 있다. 잔돈으로 10, 50, 100, 500 그리고 최대 갯수 15개로 설정 되어 있다. 사용자가 천원을 넣었을때 이때 환전 자판기가 거슬러 줄수 있는 가짓수를 계산하여라. (잔돈 설정, 최대갯수 설정에 확장성이 있게 짤것)

 

난이도

IQ 75

 

목표시간

15분

 

문제정답(사용언어:python)

1. deque 와 // 를 이용

from collections import deque

cnt =0
def change(target, coins, usable):
    global cnt
    coin = coins.popleft()
    if len(coins) == 0:
        if target//coin <= usable:
            cnt +=1
    else :
        for i in range(0, target // coin +1 ) :
            change(target - coin*1, coins,copy(), usable -i)

change(1000, deque([500, 100, 50, 10]) , 15)
print(cnt)

 

배운점

파이선 // 연산기호 => 나머지 연산이후 정수부분만 반환한다.

단순하게 중첩 for문을 이용하여 풀면 쉽고 간단한 문제. 하지만 문제에서는 확장성을 고려하여 재귀형태로 답을 요구한듯 하다. 절차형 언어에서는 재귀보다는 반복문을 선호하지만 함수형 언어에서는 반복문보다는 재귀를 선호 한다고 한다. 이책에 모든 풀이는 파이썬으로 작성되어 있어서 대부분의 반복문 처리할 내용들이 재귀로 풀이되어 있다. 

여지껏 재귀는 디버깅이 쉽지 않고 코드 이해도를 떨어트린다고 생각해서 기피해왔지만 알고리즘적인 문제 해결면에서는 재귀적인 표현도 괜찮은것 같다. 이참에 재귀표현에 익숙해져야 겠다.

 

728x90
728x90

문제

길이 n cm의 한 막대를 1cm 단위로 자른다. 단, 하나의 막대는 한번에 한 사람만이 자를 수 있다. 잘린 막대가 3개면 동시에 3명이 자를 수 있다. 최다 m명이 있을 때 막대를 자르는 최소 횟수를 구하시오. 예를 들어 n=8, m=3일때 4번 자를 수 있다.

 

난이도

IQ 70

 

목표시간

10분

 

문제풀이(사용언어:C#, 작성도구:VisualStudio2019)

//20.01.09
//
//

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _4_CutStick
{
    class Program
    {
        static void Main(string[] args)
        {
            int STICK_LENGH = 100;
            int MEMBER_COUNT = 5;
            
            double depth = Math.Ceiling(Math.Log(STICK_LENGH, 2));
            Console.WriteLine("length :: " + STICK_LENGH);
            Console.WriteLine("members :: " + MEMBER_COUNT);
            Console.WriteLine("depth :: " + depth);

            double resultCnt = 0f; //최종 자르는 횟수
            int totalCutCnt = 0;   //좌우로 2의 제곱으로 증가하면서 자르는 횟수
            int remainCut=0;       //사람이 부족해서 다음 스텝에서 잘라야 하는 횟수

            for (int i=0; i<depth; i++)
            {
                totalCutCnt++;
                int cutCnt = (int)Math.Pow(2, i);

                if (MEMBER_COUNT < cutCnt)
                {
                    remainCut += cutCnt - MEMBER_COUNT;
                }

                //마지막 뎁스 일때
                if (i == (depth-1) )
                {
                    //2의 제곱수가 아니면 홀수 단위로 자르게 되어 추가적으로 잘라야한다.
                    if ( (Math.Log(STICK_LENGH,2) - (int)Math.Log(STICK_LENGH,2) ) != 0)
                    {
                        int addCutCnt = (int)Math.Pow(2, i - 1);

                        if(MEMBER_COUNT < addCutCnt)
                        {
                            totalCutCnt++;
                            remainCut += addCutCnt - MEMBER_COUNT;
                        }
                    }
                }
            }

            resultCnt = totalCutCnt + Math.Ceiling((double)remainCut/MEMBER_COUNT);
            Console.WriteLine("least cut count::" + resultCnt);

        }
    }
}

 

문제정답(사용언어:python)

1. solution_1은 문제 그대로를 재귀로 옮긴 방식

2. solution_2 발상의 전환. m명이 n막대를 자르는게 아닌 m명이 1cm 막대를 n cm 막대로 붙여 나간다고 생각.

 

##solution_1
def cutbar(m, n, current): # current는 현재 막대의 개수
    if current >= n:
        return 0 # 잘라내기 완료
    elif current < m:
        return 1 + cutbar(m, n, current*2) # 다음은 현재의 2배가 된다
    else :
        return 1 + cutbar(m, n, current+m) # 가위 수만큼 증가

print(cutbar(3, 20, 1))
print(cutbar(5, 100, 1))

##solution_2
def cutbar(m, n): 
    count = 0;
    current = 1 # current는 현재 막대의 길이
    while n > current:
        print(current)
        current += current if current <m else m
        count +=1
    print(count)

cutbar(3, 20)
cutbar(5, 100)

 

배운점

깊이 우선 방식을 이용한 재귀구현.

깊이 우선 방식의 경우 모든 탐색 경로를 찾을시에는 메모리 공간을 아낄수 있다.

너비 우선 탐색은 가장 빠른 탐색 경로 하나를 발견해야하는 경우에는 유리하다.

 

728x90
728x90

- UI 매니저

- sound 매니저

- 재사용 스크롤 뷰

- 폰트 변경 에디터

- 이미지 속성 설정 에디터

- 토글

- stream asset

- 스몰 로딩(네트워크 매니저)

- asset bundle 

- 2d sprite

728x90
728x90

실시간 시각효과를 낼 수 있는 unity 툴로 gup로 실행되는 컴퓨트 세이더 및 노드 기반의 워크플로를 사용한다.

어느 개발자 인터뷰를 보면 ta들로부터 호평을 받고 있는거 같다. 확실히 유니티의 gui기반의 작업방식은 아티스트들에게 환영 받는것 같다. 내부적으로 들어가면 쉐이더,그래픽스 개념이 필요해서 코어하지만 gui 작업만을 통해서도 상당히 괜찮은 작업이 되는듯 하다.  실무에서 직접 작업할 일은 별로 없을것 같지만.. 정식버전에 추가되어 있다고 하니 한번쯤 써봐야 겠다.

 

참고

https://blogs.unity3d.com/kr/2018/11/27/creating-explosive-visuals-with-the-visual-effect-graph/

728x90
728x90

Ray tracing

유니티에서 hdrp 기능을 지원하면서 포함한 랜더링 기법으로 기존에도 있던 개념이나 알고리즘 특성상 수많은 연산이 필요하기에 최근 그래픽카드 발달로 인해 ray tracing이 적용된 제품이 등장하고 있는것 같다. 물론 실시간 렌더링이 필요한 게임에서는 적용하기 힘들다고 한다.

 

ray tracing은 픽셀 하나에 하나의 광선을 쏘고 광선이 충돌,반사,굴절 되는 지점들을 광선을 추적에 연산하는 알고리즘이다.

 

Path tracing

Path tracing is a ray tracing algorithm that sends rays from the Camera and, when a ray hits a reflective or refractive surface, recurses the process until it reaches a light source. The series of rays from the Camera to the Light forms a "path".

 

path tracing은 ray tracing 알고리즘의 일종으로 카메라부터 광원까지 도달하기까지의 일련의 광선을(굴절, 반사되는 등) path라고 한다.

 

비슷한 방식으로 랜더링 알고리즘이란것은 이해했으나 둘의 정확한 차이에 대해서 만족할만한 답을 찾진 못했다. ray tracing은 하나의 pixel 당 하나의 광선을, path tracing은 하나의 pixel에 수많은 광선을 쏘아서 연산을 한다고 하는데.. 그 이후 원리를.. 잘모르겠다.. 

 

 

참고

https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@7.1/manual/Ray-Tracing-Path-Tracing.html

728x90
728x90

유니티 버전 2018.1 에서 도입된 SRP(Scriptable Render Pipeline)이라는 시스템이 되어 프로젝트에 맞는 렌더링 파이프라인을 만들 수 있게 되었다. SRP에서는 LWRP(경량 ,lightweight), HDRP(고해상도) 두 가지 파이프라인이 제공 된다. HDRP는 PC, 콘솔 플랫폼 용도로 권장된다.

2019.3버전 부터 경량 렌더 파이프라인인 srp의 경량랜더파이프라인인 lwrp가 urp로 변경된다. 다양한 부분 업그레이드 되었지만 hdrp와는 구분된다. hdrp는 고사양 하드웨어를 바탕으로 고성능을 발휘하기에 적합하고 urp는 범용성과 유연성이 특징이다.

 

유니티 최신버전에서 package manager를 통해 릴리즈된 hdrp를 쓸수 있지만 안정성이 필요한 프로젝트에 적용하기에는 좀더 기다려야할 것같다. 공부, 포트폴리오용으로 한번 사용해봐야겠다.

 

참고

https://blogs.unity3d.com/kr/2018/09/24/the-high-definition-render-pipeline-getting-started-guide-for-artists/

 

Unity 아티스트를 위한 HDRP 안내서 - Unity Technologies Blog

이 데모에서는 유니티의 고해상도 렌더 파이프라인(High Definition Render Pipeline, 이하 HDRP)을 사용하여 렌더링할 씬을 제작하는 방법을 보여드리겠습니다. 1) 새로운 HDRP 프로젝트를 시작하고, 2) 임포트한 에셋의 머티리얼을 업그레이드하고, 3)...

blogs.unity3d.com

https://blogs.unity3d.com/kr/2019/09/20/how-the-lightweight-render-pipeline-is-evolving/

 

URP - 경량 렌더 파이프라인의 진화 - Unity Technologies Blog

Unity 2019.3버전부터 경량 렌더 파이프라인(Lightweight Render Pipeline, LWRP)이 유니버설 렌더 파이프라인(Universal Render Pipeline, URP)으로 변경되었습니다. URP는 아름다운 그래픽과 뛰어난 성능을 제공하는 강력한 솔...

blogs.unity3d.com

 

728x90

'게임엔진 > UNITY 3D' 카테고리의 다른 글

무한 스크롤 방식 맵(배경, 오브젝트) 제작  (0) 2020.01.30
비주얼 이펙트 그래프  (0) 2020.01.08
Ray Tracing, Path tracing  (0) 2020.01.08
728x90

문제

1~100까지 카드가 뒤집어져 있다. n번쨰 카드를 n-1씩 이동하여 카드를 뒤집는다. (n초기값 = 2) 100번째 카드까지 이러한 과정을 거쳤을때 뒤집어져 있는 카드는 ?

예)  (■:뒤 :앞)

n=2   

n=3   

n=4   

 

난이도

IQ 70

 

목표시간

10분

 

문제풀이(사용언어:C#, 작성도구:VisualStudio2019)

//20.01.08
//
//

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _3_TurnCardOver
{
    class Program
    {
        static void Main(string[] args)
        {
            //0:뒤 1:앞
            int[] deck = new int[100];

            //deck 초기화(모든 카드가 뒤집힌 상태)
            for(int i=0; i<deck.Length; i++)
            {
                deck[i] = 0;
            }

            //뒤집기
            for (int i=2; i<=deck.Length; i++)
            {
                for(int j=i-1; j< deck.Length; j+=i)
                {
                    if (deck[j] == 0)
                        deck[j] = 1;
                    else
                        deck[j] = 0;
                }
            }

            //결과
            for (int i = 0; i < deck.Length; i++)
            {
                if (deck[i] == 0)
                {
                    Console.WriteLine(i+1);
                }

            }


        }
    }
}

 

문제정답(사용언어:python)

1. solution_1은 문제 그대로의 규칙대로 작성된 방법

2. solution_2는 제곱수(1,4,9,16 ..)만을 구하는 방법

 2.1 나열된 카드는 홀수 뒤집혔을때 앞면을 짝수번 뒤집혔을때 된다.

 2.2 예를 들어 16번 카드는 2 4 8 16번째 카드를 이동할떄 마다 뒤집힌다.

 2.3 2 4 8 16은 16의 약수이다

 2.4 즉 1~100까지 숫자 중에 약수가 홀수개인 숫자를 찾으면된다

 2.5 약수가 홀수개인 수는 제곱수이다.

 2.6 왜? 약수를 오름차순으로 나열했을때 각 끝 숫자들의 곱은 해당 숫자값이된다

 2.7 16의 약수의 경우 1*16=16, 2*8=16, 4*4 =16 가운데 남는 4는 4*4=16이 된다.

 2,.8 따라서 제곱수는 약수가 홀수개이다 제곱수는 문제의 정답수이다.  


# 카드의 초기화
N = 200
cards = [False] * N


## solutin_1
# 2~N까지 뒤집음
for i in range(2, N+1) :
    j=i-1
    while j < len(cards):
        cards[j] = not cards[j]
        j+=i

#뒷면이 위를 향한 카드 출력
for i in range(0,N):
    if not cards[i]:
        print(i+1)


##solutin_2
for i in range(1, N+1):
    flag = False
    for j in range(1, N+1):
        if i%j==0:
            flag = not flag
    if flag:
        print(i)

 

배운점

 파이썬의 쉬운 배열 초기화를 보고 c#에서도 가능한지 찾아보았다

    int[] myIntArray = Enumerable.Repeat(-1, 20).ToArray();

 단순히 규칙을 코드로 옮겨 문제를 풀었다. 코드로 옮기는대 시간이 걸리더라도 그전에 단순히 문제 그대로의 풀이 방식이 아닌 새로운 방법에 대해서 다양한 접근을 습관적으로하는게 좋을것 같다. 어려운 규칙은 단순화 시켜 코드작성을 하지만 단순한 규칙은 쉽게 생각을 멈추고 코딩하는 것 같다. 

 

728x90
728x90

문제

제시된 숫자와 거꾸로 나열한 숫자에 사칙연산을 넣은 계산식이 같게하라

(연산자는 최소1번 이상 쓰여야 하며 사칙연산 규칙을 지켜야한다)

351  3*51 =153

621 6*21 = 126

 

난이도

IQ 70

 

목표시간

10분

 

문제풀이(사용언어:C#, 작성도구:VisualStudio2019)

제한시간 내에 풀지 못했다.

문자열 상태에서 모든 경우의 수의 연산자를 대입해서

스택,큐를 이용해서 문자열 식을 후위식으로 전환해서 계산하려고 했다.

 

문제정답(사용언어:python)

1. *를 제외한 다른 연산자를 한번이라도 쓰게되면 4자리를 넘지 못하므로 다른 연산자는 신경쓰지 않아도 된다.

    (999+9 = 1008와 같은 덧셈만 있는 몇가지 경우 4자리를 넘기는 경우가 몇번 있긴 하다 하지만 제외.)


import re

op = ["*",""]

for i in range(1000,10000):
    c = str(i)
    for j in range(0,len(op)):
        for k in range(0,len(op)):
            for l in range(0,len(op)):
                val = c[3] + op[j] + c[2] + op[k] +c[1] + op[l] + c[0]

                # 0으로 시작하는 숫자가 있는지 확인하고 있는 경우 제거
                val = re.sub(r"0(\d+)", r"\1",val)

                #연산자를 하나라도 넣은 경우
                if len(val) >4 :
                    if i == eval(val) :
                        print(val, "=", i);

 

배운점

연산자를 대입하는 경우의 수는 무척 간단했으나.. 문자열 계산기를 단시간에 만들기는 좀 버거웠다.. 그런데 eval()로 문자열 계산을 처리하는 답지를 보니 무척 허탈하다.. api를 소개하는 책인가?;

 

 

728x90
728x90

문제

10진수, 2진수, 8진수 어느 것으로 표현하여도 대칭수가 되는 수 중, 10진수의 10 이상에서의 최솟값을 구해 보세요.

예) 9(10진수)= 1001(진수) = 11(8진수)

 

난이도

IQ 70

 

목표시간

10분

 

문제풀이(사용언어:C#, 작성도구:VisualStudio2019)

//20.01.06
//
//

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace QuizPalindrome
{
    class Program
    {
        public const int MIN_NUM = 10;

        static void Main(string[] args)
        {
            Calculator calc = new Calculator();


            for (int i = 1; i < 1000; i++)
            {

         
                //10진수
                bool isPalindromeDemical = calc.CheckPalindrome(i + "");
                Console.Write(i + "/");

                //2진수
                bool isPalindromeBinary = calc.CheckPalindrome(calc.BinaryFromDemical(i));
                Console.Write(calc.BinaryFromDemical(i) + "/");

                //8진수
                bool isPalindromeOctal = calc.CheckPalindrome(calc.OctalFromDemical(i));
                Console.Write(calc.OctalFromDemical(i));

                Console.WriteLine("");

                //if (i == 9)
                //{
                //    Console.WriteLine(isPalindromeDemical + " " + isPalindromeBinary + " " + isPalindromeOctal);

                //}

                if (isPalindromeBinary && isPalindromeDemical && isPalindromeOctal)
                {
                    if (i > MIN_NUM)
                    {
                        Console.WriteLine("min palindrome :: " + i);
                        break;
                    }

                }

            }
        }
    }

    class Calculator
    {
        public Calculator()
        {
            
        }

        public bool CheckPalindrome(string _target)
        {
            string target = _target;

            if(_target.Length == 1)
            {
                return true;
            }

            for(int i=0; i<target.Length/2; i++)
            {
                if(target[i] == target[target.Length -1 -i])
                {
                    
                }
                else
                {
                    return false;
                }
            }

            return true;
        }


        //10진수를 2진수로 변환한 문자열 얻는 함수
        public string BinaryFromDemical(int num)
        {
            string sBinary = "";
            int iDemicalNum = num;

            while (true)
            {
                sBinary += (iDemicalNum%2) + "";
                iDemicalNum = (iDemicalNum - (iDemicalNum % 2)) / 2;

                if(iDemicalNum < 2)
                {
                    if(iDemicalNum != 0)
                    {
                        sBinary += iDemicalNum;
                    }

                    break;
                }
            }

            sBinary = ReverseString(sBinary);

            return sBinary;
        }

        //10진수를 8진수로 변환한 문자열을 얻는 함수
        public string OctalFromDemical(int num)
        {
            string sOctal = "";
            int iDemicalNum = num;

            while (true)
            {
                sOctal += (iDemicalNum % 8) + "";
                iDemicalNum = (iDemicalNum - (iDemicalNum % 8)) / 8;

                if (iDemicalNum < 8)
                {
                    if(iDemicalNum != 0)
                    {
                        sOctal += iDemicalNum;
                    }

                    break;
                }
            }

            sOctal = ReverseString(sOctal);

            return sOctal;
        }

        //문자열 리버스 함수
        public string ReverseString(string _target)
        {
            string sResult = "";
            string target = _target;

            for(int i= target.Length-1; i>=0; i--)
            {
                sResult += target[i];
            }

            return sResult;
        }
    }
}

 

문제정답(사용언어:python)

1. 2진수는 무조건 1로 시작하므로 대칭이 되기 위해선 끝자리 역시 무조건 1이 되어야 한다.

2. 따라서 정답은 무조건 홀수이다.

3. 11부터 2씩 증가시키면서 검색한다.

# 11부터 탐색 개시
num = 11

while True:
    #진번에 따른 변수를 선언
    num_10 = str(num)
    num_8 = oct(num).replace("0o","")
    num_2  = bin(num).replace("0b","")

    #앞뒤가 같은지 확인
    if num_10 == num_10[::-1]\
        and num_8 == num_8[::-1]\
        and num_2 == num_2[::-1]:
        break

    #홀수만 탐색하므로 2씩 늘림
    num += 2

   

 

배운점

파이썬 기본 api 함수에 (문자열 역순을 구해주는 함수도 있네..) 놀랐고 c#을 쓰는 본인인 너무 기본적인 api에 무지 했다는 점에 두번 놀랐다.. 코드량의 차이가 이렇게 날 줄이야... 간단한 기능을 하는 api들이야 직접 구현하기에 어려움이 없다고 느껴서 api 사용을 등한시 했었는데.. 이정도로 코드양이 찬다고 생각하니.. 놀랍다..

문제는 무척 심플하고 간단했기 때문에.. 별로 할말이 없다. 정답풀이에서 검색 범위를 홀수로 줄여서 탐색범위를 줄였지만 실무 코드에서는 저런 아이디어를 따로 주석으로 처리해놓지 않으면 오히려 코드 해석하기 힘들거 같기 때문에..

 

c# 에서 진수변환 처리 해주는 만능 Conver.ToString()이 있다.

물론 문자열을 쉽게 역순으로 전환하는 api 사용법도 있다.

 

수정

//20.01.06
//
//

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace QuizPalindrome_modified
{
    class Program
    {
        public const int MIN_NUM = 10;

        static void Main(string[] args)
        {
            Calculator calc = new Calculator();

            for (int i = 1; i < 1000; i++)
            {
                //10진수
                bool isPalindromeDemical = calc.CheckPalindrome(i + "");
                Console.Write(i + "/");
                
                //2진수
                bool isPalindromeBinary = calc.CheckPalindrome(Convert.ToString(i,2));
                Console.Write(Convert.ToString(i, 2) + "/");

                //8진수
                bool isPalindromeOctal = calc.CheckPalindrome(Convert.ToString(i,8));
                Console.Write(Convert.ToString(i, 8));

                Console.WriteLine("");

                if (isPalindromeBinary && isPalindromeDemical && isPalindromeOctal)
                {
                    if (i > MIN_NUM)
                    {
                        Console.WriteLine("min palindrome :: " + i);
                        break;
                    }

                }
            }
        }
    }

    class Calculator
    {
        public Calculator()
        {

        }

        public bool CheckPalindrome(string _target)
        {
            string target = _target;
            string reverseTarget = new String(target.ToCharArray().Reverse().ToArray());

            if(target == reverseTarget)
            {
                return true;
            }

            return false;
        }


   

     
    }
}

new String(target.ToCharArray().Reverse().ToArray());

Convert.ToString(i,2)

의 사용으로 짧고 간단하고 이해하기 쉬워진 코드를 보라!

728x90

+ Recent posts