정보

2년 전에 봤던 E모 회사 입사 실기 시험

– 기존 문제가 딱히 정확하게 기억이 안 나므로 요약함.
– 시험 시간은 5시간이었음.
– 난 바보같이 이걸 제대로 못 품. 예제 중 엄청 긴 문자열의 처리 속도가 너무 늦음. 근데 나중에서야 괜찮은 알고리즘이 생각남.

1. 문자열의 서브스트링을 있는대로 구하고, 그 중에 서브스트링 길이 * 해당 서브스트링 총 개수(이 값을 M이라고 함)가 가장 큰 녀석을 하나 뽑아서 출력
2. M이 같은 서브스트링의 경우 서브스트링의 길이가 짧은(즉, 총 개수가 더 많은) 녀석을 뽑아서 출력
3. 서브스트링 길이도 같고 총 개수도 같은 서브스트링은 먼저 것을 출력
4. 총 개수가 1인 서브스트링은 출력하지 않음
5. 위의 조건에 만족하는 서브스트링이 한 개도 없을 경우 NULL 출력
6. 문자열은 대소문자를 구별하며, 입력받은 문자열이 [a-z][A-Z][0-9]에 해당하지 않거나 길이가 0인 문자열을 입력받으면 프로그램을 종료
7. 모든 입출력은 표준 입출력을 사용할 것

예1)
입력 – test
출력 – t:2
예2)
입력 – 12aaaaaa
출력 – a:6
예3)
입력 – abB
출력 – NULL
예4)
입력 – Thisisatest
출력 – is:2
예5)
입력 – ab12ab12abab12
출력 – ab12:3

광고
정보

안드로이드 에뮬레이터가 화면 밖을 벗어나 제어를 못 할 때

안드로이드 에뮬레이터를 실행할 때 이렇게 제목표시줄이 화면을 벗어나 제어를 못 하는 경우가 있습니다. Alt + Space를 눌러 이동(M) 항목에서 엔터, 화살표키로 내려주고 엔터를 다시 눌러주면 화면 내로 들어오게 됩니다. 혹은 작업표시줄에서 안드로이드 에뮬레이터의 에어로 픽을 오른쪽 클릭, 이동(M) 항목을 눌러 화살표키로 옮겨줘도 동일하게 동작합니다.

정보

Xcode에서 Entitlements 에러가 날 때

여러 아티클을 보면서 Entitlements 파일과 관련된 코드 사이닝(Code Signing) 오류를 해결하기 위해 두 달 정도 헤맸는데, mobileprovison 파일에 있는 Entitlements 속성을 가져와 entitlements 파일에 넣으면 되더군요. 대신, App Sandbox 같은 속성은 빼야 됩니다.

똑같이 진행했지만 App Sandbox 때문에 두 달을 소요…. ㅠ

 

참고: [1]

정보

100Mbps 이더넷과 1Gbps 이더넷의 차이

요즘 기가인터넷이라고 불리는 1Gbps 인터넷 망이 점차 보급이 되어가고 있습니다. 제가 다니고 있는 충남대학교도 조만간 기가인터넷망이 설치될 예정이라고 들었고요. 근데 1Gbps, 즉 초당 비트 수가 100Mbps보다 10배 높은 기가 인터넷은 100Mbps 인터넷망과 어떤 차이가 있을까요?

이론상으로 100Mbps 이더넷은 초당 12MB의 데이터를 전송할 수 있습니다. 그리고 1Gbps 이더넷은 초당 125MB를 전송할 수 있죠. 인터넷 전송 속도가 빨라지냐고요? 아닙니다. 대역폭이 10배 늘어나기 때문에 가능한 전송량입니다.

물론 송수신하는 데이터가 크거나, 여러 프로그램에서 동시에 네트워크 처리를 하는 경우에는 속도가 100Mbps 이더넷을 사용할 때 보다 훨씬 빠를 수 있지만, 한국과 LA의 게임 플레이어가 온라인으로 게임을 플레이했을 때 나오는 높은 핑은 그대로입니다.

고속도로를 생각해보면 빠르겠습니다. 최대 100Km/s의 속도를 낼 수 있는 고속도로가 2차선이냐 20차선이냐를 생각해보세요. 결국 낼 수 있는 속도는 100Km/s이지만 많은 차량이 도로를 더 넓게 쓸 수 있으므로 더 많은 차량이 같은 시간에 이동할 수 있죠.

100Mbps와 1Gbps는 결국 전송 속도가 아니라 대역폭을 늘림으로써 더 많은 데이터를 한번에 가져올 수 있도록 했기 때문에 동영상(특히 Full HD 이상 급)이나 무손실 압축 음원의 스트리밍이나 다운로드가 더 수월해진다는 장점이 있습니다만, 거리가 멀어질 수록 지연되는 시간은 결국 같기 때문에 지구 반대편의 플레이어와 실시간으로(그러니까, 5ms 이하의 지연으로) 게임을 같이 플레이하려면 기술이 더 발전해야 할 겁니다.

+ (2015.12.23) 5ms 이하의 지연으로 지구 반대편의 플레이어와 실시간으로 게임을 하려면?

일단 1초에 빛이 얼마나 빨리 갈 수 있는지 지구의 둘레 길이를 이용해 비교해봤습니다.

1000ms = 6.939640231481481

1초(1000밀리초)에 6.93바퀴를 돌 수 있습니다.

5ms = 0.0346982011574074

실시간이라고 할 수 있는 5ms(5밀리초)에 맞춰봤더니 겨우 0.03바퀴밖에 돌지 못 합니다.

50ms = 0.3469820115740741

50밀리초에는 0.34바퀴

150ms = 1.040946034722222

150밀리초에 이르러서야 1.04바퀴를 돌 수 있게 됩니다. 지구 반대편 플레이어와 게임을 한다고 하면 상대방에게 내 패킷이 도달하는 시간 또는 그 반대의 시간이 반으로 뚝 자른 75ms가 걸리게 되네요. 빛을 이용해서도 지구 반대편에 있는 사람과는 실시간으로 게임을 즐기기가 어렵군요. 물론 75ms도 실시간이라면 실시간일 수는 있지만… 0.1초 가까이 차이가 나는걸 실시간이라고 할 수 있을지…

여기에 사실 라우터를 거치는 시간 등을 도합하면 150~300ms 근처로 나타나게 될겁니다. 라우터나 스위치 등의 기기에서 프로세서를 거치게 되면 어쩔 수 없이 느려지기 마련이죠.

정보

Windows에서 타블렛 입력받기

1b05ee29562071a634b8601b4bbbeaf3Windows 운영체제에서 타블렛 입력을 받기 위해서는 WinTab32.dll의 사용을 병행해야 합니다. WinTab32.dll을 이용한 타블렛 입력 방법은 웹에서도 왠만한 검색어를 잘 선정해서 검색하지 않으면 자료가 나오지 않을 정도로 자료 구하기가 희박합니다. 사실, WACOM의 개발자 페이지(http://www.wacomeng.com/index.html)에 가보면 예제 코드가 존재합니다. 근데, 그 예제 코드라는게 전부 실행하면 프로그램이 종료할 때까지 마우스와 타블렛의 인식이 따로놀게 됩니다. 즉, 타블렛 펜을 움직여도 마우스는 움직이지 않지요. 타블렛으로 WM_MOUSEMOVE와 같은 메시지를 받을 수 없게 된다는 얘기입니다.

그럼, 타블렛 입력을 받아봅시다. 먼저, WACOM 개발자 페이지의 Windows 탭에서 예제 코드를 받습니다. 압축을 풀어서 내용물을 확인하면 Include 폴더와 WacUtils 폴더가 있습니다. 이 두 폴더 모두 필요합니다. 개발하는 프로젝트(이 포스트에서는 Win32 프로젝트 템플릿에 빈 프로젝트를 체크하지 않은 상태로 프로젝트를 만들어 보여드리겠습니다)로 복사합니다. Utils.c 파일은 사용자 컴파일이 필요하므로 프로젝트 컴파일 목록에 추가합니다.

11a260dad111223faa4ddefd59b7879d

이제 상단에 Utils.h 파일을 포함시키고 프로그램이 시작할 때 LoadWintab 함수를, 프로그램이 끝날 때 UnloadWintab 함수를 호출합니다.
(이 부분부터 사용자에 따라 오류가 발생할 수 있으나 모두 수정할 수 있는 오류입니다. 아래에서 파일을 받아보시면 아시겠지만 원본 예제의 헤더 및 소스 파일에서 일부 수정한 부분이 있습니다.)

bcdba802eb3177a4c91f54a62893dadc

위 스크린샷에는 없지만 프로그램이 return을 호출하기 전(프로그램 종료 전)에 UnloadWintab 함수를 호출하고 있습니다.

이제 패킷을 구성해야 합니다. 사용자가 어떻게 구성하느냐에 따라 패킷이 받아오는 데이터가 달라질 수 있습니다.

이제 창이 생성되면 WinTab을 설정하도록 합니다. 여기서는 창 생성 메시지를 받았을 때 설정하도록 했습니다.

1149dc33b5394bfe2fd82314e59c826d

마지막으로 패킷을 받도록 하겠습니다. 패킷을 받는 것은 메시지로만 가능합니다.

65107385934cbb47736831c492f2b0f7

실행하고 타블렛으로 꾹 누르거나 지우개로 입력하면 창 제목 표시줄이 변경되는 것을 보실 수 있습니다.

X, Y 좌표는 절대 좌표로 나올 수 있기 때문에 WM_MOUSEMOVE로 받는 편이 가장 좋습니다. 위에서는 그렇게 설정하지 않았지만 기본 제공하는 WACOM의 예제들을 보시면 어떻게 WT_PACKET으로 좌표까지 받을 수 있는지 확인하실 수 있을 것입니다.

Example

정보

자연스러운 펜툴 만들기 – 2

지난번에 Polygon과 Ellipse를 이용하여 자연스러운 펜툴을 만드는 방법을 연구해봤는데, 그림 그리는 도구에서 브러시에 알파값을 먹이는 경우가 잦기 때문에 시도해봤더니 겹쳐서 그리다보니 전부 보이더군요.

비툴, 사이툴, 오에카키 등은 위의 방법과 다른 방법을 사용한다는 점을 하루종일 연구하면서 알게 되었습니다(사실 도저히 모르겠어서 리버스 엔지니어링도 시도해봤는데 눈에띄는 코드가 없어서 포기하고 픽셀 움직임을 중점으로 봤습니다 ㅠㅠ). 특히 비툴이 눈에 잘 띄더군요. 그 방법이랄게, 선을 그리는 알고리즘을 개량하면 되는 겁니다.

선을 그리는 알고리즘은 직선의 방정식 이용, DDA 알고리즘, 브래슨햄 알고리즘 등 매우 다양합니다. 이 중에서 저는 딱히 구현하기 귀찮아서 그냥 64비트 멀티코어 OS 원리와 구조 2권에 나오는 선 그리기 함수를 조금 개량해서 그리기에 시도해봤습니다. 자세한 알고리즘은 선그리기 알고리즘( http://setimets.blog.me/30068320547 ) 이곳을 참고해보시기 바랍니다. 액션스크립트 예제 중심이지만 다른 언어로 쉽게 옮길 수 있을겁니다.

아래는 그 소스 코드의 일부입니다.

private void DrawLine ( Graphics g, PointF p, PointF p2 )
{
    int iDeltaX, iDeltaY;
    int iError = 0;
    int iDeltaError;
    int iX, iY;
    int iStepX, iStepY;
 
    iDeltaX = (int)(p2.X - p.X);
    iDeltaY = (int)(p2.Y - p.Y);
 
    if ( iDeltaX < 0 )
    {
        iDeltaX = -iDeltaX;
        iStepX = -1;
    }
    else iStepX = 1;
 
    if ( iDeltaY < 0 )
    {
        iDeltaY = -iDeltaY;
        iStepY = -1;
    }
    else iStepY = 1;

    if ( iDeltaX > iDeltaY )
    {
        iDeltaError = ( ( int ) iDeltaY ) << 1;
        iY = (int)p.Y;
        for ( iX = ( int ) p.X; iX != p2.X; iX += iStepX )
        {
            DrawPoint ( g, new PointF ( iX, iY ) );

            iError += iDeltaError;

            if ( iError >= iDeltaX )
            {
                iY += iStepY;
                iError -= ( ( int ) iDeltaX ) << 1;
            }
        }
        DrawPoint ( g, new PointF ( iX, iY ) );
    }
    else
    {
        iDeltaError = ( ( int ) iDeltaX ) << 1;
        iX = ( int ) p.X;
        for ( iY = ( int ) p.Y; iY != p2.Y; iY += iStepY )
        {
            DrawPoint ( g, new PointF ( iX, iY ) );

            iError += iDeltaError;

            if ( iError >= iDeltaY )
            {
                iX += iStepX;
                iError -= ( ( int ) iDeltaY ) << 1;
            }
        }
        DrawPoint ( g, new PointF ( iX, iY ) );
    }
}

결과는 성공적이었습니다. 거의 비슷하게 구현이 되었습니다.

e20f0581f32b78f829e05a1b685f2ae7

정보

자연스러운 펜툴 만들기 – 1

보통 GDI 등의 라이브러리를 사용하여 그림판 같은 프로그램을 만들면 그린 점을 모두 이어 화면에 출력합니다. 예를 들면 Mouse Move 이벤트로 점을 받을 때마다 이전 점과 현재 점을 DrawLine과 같은 함수로 이어 그리는 것이지요. 가장 좋은 방법은 베지어(Bezier) 곡선을 그리는 방법입니다만, 중간 단계 점이 더 있어야 완성할 수 있는데다, 펜의 두께가 점마다 다르게 하는 것을 구현하려면 직접 구현해야 하므로 이 방법보다 다른 방법을 이용하는 편이 좋을 것이라고 생각했지요.

GDI나 GDI+에는 Polygon을 그리는 방법이 있습니다. 각 점에 일단 원을 그려놓고, 두 원을 이 Polygon으로 이어주면 되지요.

513bfea183a4f09262d9d063e982f1d4

Polygon의 좌표는 첫 번째 원과 두 번째 원을 잇는 두 점의 시작점과 끝점들입니다. 총 네 개의 점이 있지요. 그렇다면, 이 위치를 어떻게 하면 잡을 수 있을까요?

한 원에 두 개의 점이 있는데, 중심점으로부터의 거리는 같습니다. 위치만이 중심점으로부터 얼마나 각도가 틀어졌느냐의 문제인데, sin 함수와 cos 함수를 이용하면 쉽게 구할 수 있습니다. 아래는 예제의 소스 코드의 일부입니다.

PointF [] poly = new PointF [ 4 ]; 
double angle = Math.Atan2 ( lastp.y - p.y, lastp.x - p.x ); 
poly [ 0 ] = new PointF ( lastp.x - ( float ) Math.Sin ( angle ) * lastp.size, lastp.y + ( float ) Math.Cos ( angle ) * lastp.size ); 
poly [ 1 ] = new PointF ( lastp.x + ( float ) Math.Sin ( angle ) * lastp.size, lastp.y - ( float ) Math.Cos ( angle ) * lastp.size ); 
poly [ 2 ] = new PointF ( p.x + ( float ) Math.Sin ( angle ) * p.size, p.y - ( float ) Math.Cos ( angle ) * p.size ); 
poly [ 3 ] = new PointF ( p.x - ( float ) Math.Sin ( angle ) * p.size, p.y + ( float ) Math.Cos ( angle ) * p.size ); 
e.Graphics.FillPolygon ( blackBrush, poly );

폴리곤 정점의 순서는 크게 상관은 없습니다만, 삼각형 두개가 연결된 것을 보고 싶지 않으시다면 순서를 연결되게 하는 것이 좋습니다.

정보

GitHub for Windows의 Clone 및 Sync 작업이 오류가 날 때

GitHub for Windows의 Clone 및 Sync 작업이 오류가 날 때 웹에서 결과를 찾기 어렵다면 C:WindowsSysWOW64libcurl-4.dll 파일을 제거해보세요.

또는 C:WindowsSystem32libcurl-4.dll, C:WindowsSystem32libcurl.dll, C:WindowsSysWOW64libcurl.dll이 있다면 제거해보세요.

git for Windows의 경우 HTTPS 인증 작업을 위해 libcurl을 사용하는데, 그 libcurl의 구버전이 시스템 폴더에 들어있기 때문에 발생하는 오류입니다.

git for Windows에서 문제가 발생하면 이를 사용하는 GitHub for Windows가 문제가 생길 수 밖에 없지요.