2010년 2월 25일 목요일

안드로이드폰 메모리 제한 for Apps

넥서스원을 기다리는 유저의 입장으로 안드로이드의 어플리케이션 저장 용량에 제한이 걸려있다라는 사실에 꽤나 관심을 가지게 되었습니다.

우선, 국내 언론에서는 상당한 문제점으로 지적하고 있군요. 물론 해외에서도 또한 같은 문제로 이슈되고 있더군요.

문제는 이렇습니다.

아이폰 3GS 에서는 16GB , 32GB 스토리지를 제공하게 되는데 이 모든 스토리지를 App를 위한 공간으로 사용할 수 있다는 점입니다. 따라서 거의 unlimited에 가깝게 많은 어플리케이션을 설치할 수 있지요.

허나, 안드로이드의 경우 확장 메모리카드 스토리지에 App을 설치할 수 없습니다. 따라서 기본 응용프로그램을 제외한 100MB 내외의 용량에서만 어플리케이션을 설치할 수 있지요.

이 이슈에 대해서 의견이 분분합니다. 용량에 제한이 걸려있어서 문제가 있다!!! 이거 뭐냐 너무 실망이다~~ 다른 폰을 사야겠다~~ 등등...

그런데 실제로 넥서스원 혹은 드로이드 폰을 사용하는 유저의 입장은 좀 다르더군요. 실제 자신의 폰이라 애착이 가서 옹호적인 글을 쓴것은 아닐까라는 의구심이 들기는 하지만...ㅎㅎㅎ

그들의 주장을 압축해보면 다음과 같습니다.

1. 구글에서 이 문제에 대해서 현재 수정중에 있다. 그러므로 곧 우리는 많은 SD Card를 이용한 어플리케이션 설치를 지원받을 수 있을 것이다. (이렇게 되면 아마도 플랫폼 업그레이드가 필요하겠지요?)
2. 현재 나는 120개 이상의 어플리케이션을 쓰고 있지만 용량제한은 아무 문제가 되지 않는다. 이유는 배포되는 어플리케이션의 용량이 너무나 작기 때문이다. 일반적으로는 1MB 이하라고 생각하면 된다. 10kb , 100kb 도 많다.

그런데 2번에 대한 주장은 좀 이해하기 힘들더군요. 앞으로 더 많은 어플리케이션이 쏟아질 것이고 그렇게 되면 용량을 많이 차지하는 어플도 존재하게 될 것이고 말이죠.

이를테면 게임의 경우에는 아무래도 용량이 커지겠지요.

저는 구글에서 어서 이 문제를 해결해주었으면 하는 바람을 가지고 넥서스원을 기다리고 있습니다.

아무리 그런다 한들 옴니아2 보다야 100배 좋지 않겠습니까? ㅎㅎㅎ *(삼성 안티는 아니에요 옴니아 안티지 ㅋ)

2010년 2월 19일 금요일

[Sort] Selection Sort

Selection Sort(선택 정렬)은 앞서 다룬 Bubble Sort와 마찬가지의 복잡도를 가진다. 그러므로 많은 데이타의 정렬 위해서 쓰기에는 그 퍼포먼스가 현저하게 떨어진다.

하지만 Bubble Sort와 마찬가지로 그 구현 방법에 있어서 빠르기 때문에 작은 단위의 데이타 정렬에서 이용하기에 적합하다고 할 수 있다.

Selection Sort는 배열(혹은 리스트)에서 가장 작은 값을 찾아내어 그 값을 최앞단에 위치 시키는 방식이다.

Sort 대상 : 8 5 1 9 2

이렇게 5개의 숫자가 있다고 가정했을 때 다음과 같은 과정을 보인다.

8 5 1 9 2          => 최소값을 찾아낸다
1 5 8 9 2          => 1과 비교 대상의 첫번째 인덱스와 바꾼다.
5 8 9 2             => 최소값이 맨 앞단으로 옮겨졌기 때문에 인덱스를 증가하여 비교한다.
2 8 9 5             => 다시 최소값을 찾아 비교 대상의 첫번째 인덱스와 바꾼다.
8 9 5               => 인덱스를 증가하여 다시 비교한다.

위 과정을 배열의 마지막까지 진행을 하게 되면 정렬이 완료된다.

다음은 프로그램으로 나온 과정이다.

8 , 5  ,1 , 9 , 2
1 , 5 , 8 , 9 , 2
1 , 2 , 8 , 9 , 5
1 , 2 , 5 , 9 , 8
1 , 2 , 5 , 8 , 9
1 , 2 , 5 , 8 , 9


php로 만든 예제

[code php]
<?php
    $a = array( 8 , 5 , 1 , 9 , 2);
   
    SelectionSort(& $a);

    function SelectionSort($array)
    {
        $loop_count = count($array);
       
        for($i = 0 ; $i < $loop_count ; $i++)
        {
            $min = $array[$i];
            $minIndex = $i;
       
           /* 최소값을 찾기 위하여 루프를 돌린다. */
            for($j = $i ; $j < $loop_count ; $j++)
            {
                if($array[$j] < $min)
                {
                    $min = $array[$j];
                    $minIndex = $j;            
                }
            }
           
            swap(& $array[$i] , & $array[$minIndex]);
           
            echo implode(' , ' , $array) . "<br/>";
        }       
    }

    function swap($a , $b)
    {
        $tmp = $b;
        $b = $a;       
        $a = $tmp;               
    }

?>
[/code]

C++로 구현한 예

[code cpp]
#include <iostream>
using namespace std;

void swap(int *a , int *b)
{
    int *tmp = b;   
    b = a;
    a = tmp;
}

int main()
{
    int a[5] = {8 , 5 , 1 , 9 , 2};

    int loop_count = (sizeof(a) / sizeof(a[0]));
    int min , minIndex;
   
    for(int i = 0 ; i < loop_count ;i++)
    {
        min = a[i];
        minIndex = i;
       
        for(int j = i ; j < loop_count ; j++)
        {
            if(a[j] < min)
            {
                min = a[j];
                minIndex = j;
            }
        }
       
        swap(a[i] , a[minIndex]);
    }
   
    cout << a[0] << endl;
   
    return 0;
}
[/code]

2010년 2월 18일 목요일

[Sort] Bubble Sort

Bubble Sort 의 시간 복잡도는 상당히 높다. - worst case 일 경우에 O(n2)
그러나 이 엄청나게 느린 알고리즘을 사용하는 이유가 무엇일까...

시간 복잡도가 높다 하더라도 우리에게 주는 혜택은 당연 존재한다.

로직이 상대적으로 단순하여 프로그램상 구현하기가 쉽다.

그렇다면 그 실체는 어떤것일까,

Sort 대상 : 8 5 1 9 2

이렇게 5개의 숫자가 있다고 가정했을 경우 다음은 Bubble Sort 과정을 보여준다.

8 5 1 9 2        => 맨 처음 item과 그 다음에 존재하는 item을 비교한다.
5 8 1 9 2        => 첫번째 아이템이 다음의 아이템 보다 크므로 두 숫자를 바꿔준다.
5 8 1 9 2        => 그럼 인덱스를 한칸 옮겨 2번 아이템과 3번 아이템을 비교 한다.
5 1 8 9 2        => 역시 앞에 있는 아이템이 크므로 다음 아이템과 바꿔준다.
5 1 8 9 2        => 다시 인덱스를 한칸 옮겨 3번 아이템과 4번 아이템을 비교한다.
5 1 8 9 2        => 이번엔 뒤에 나온 아이템이 더 큰 수이므로 바꿀 필요가 없다.
5 1 8 9 2        => 인덱스를 한칸 옮겨 4번 아이템과 5번 아이템을 비교한다.
5 1 8 2 9        => 뒤에 나온 아이템이 더 작은 수이므로 앞의 아이템과 바꿔준다.

이렇게 Bubble Sort는 순차적으로 배열을 앞, 뒤로 비교를 하며 다음 인덱스로 넘어가면서 동일한 작업을 반복하게 된다.

아직 완벽하게 정렬되지 않았는데 저렇게 여러번 같은 작업을 반복하게 되면 끝내 정렬이 완료된다.

다음을 프로그램을 직접 돌려 과정을 출력한 것이다.

8 , 5 , 1 , 9 , 2
5 , 8 , 1 , 9 , 2
5 , 1 , 8 , 9 , 2
5 , 1 , 8 , 9 , 2

/////////////// 1차 정렬 종료

5 , 1 , 8 , 2 , 9
1 , 5 , 8 , 2 , 9
1 , 5 , 8 , 2 , 9
1 , 5 , 2 , 8 , 9

//////////////  2차 정렬 종료

1 , 5 , 2 , 8 , 9
1 , 5 , 2 , 8 , 9
1 , 2 , 5 , 8 , 9
1 , 2 , 5 , 8 , 9

///////////// 3차 정렬 종료

1 , 2 , 5 , 8 , 9
1 , 2 , 5 , 8 , 9
1 , 2 , 5 , 8 , 9
1 , 2 , 5 , 8 , 9

//////////// 완료


PHP로 구현한 예.

[code php]
<?php

     function BubbleSort($array , $call_reference = FALSE)
    {
        /* $array 값이 array인지 체크 */
        if(is_array($array))
        {
             /* 가장 마지막 아이템은 비교 하지 않기 때문에 -1 을 합니다. */
             $loop_count = count($array) - 1;
       
             do{
                  /* flag는 정렬이 제대로 되었을 경우 루프를 빠지기 위한 확인 값이다. */
                 $flag = false;
           
                 for($i = 0 ; $i < $loop_count ; $i++)
                 {
                     if($array[$i] > $array[$i + 1])
                     {
                         swap(& $array[$i] , & $array[$i + 1]);
                         $flag = true;    /* 정렬이 되었으면 루프를 진행하기 위하여 true로 변경 */
                     }
                 }
              }while($flag);    /* flag가 false가 될 때까지 루프 */
       
              if($call_reference === FALSE)
                 return($array);
        }
    }
       
    /* 스왑 함수 */
    function swap($a , $b)
    {
        $tmp = $b;
        $b = $a;       
        $a = $tmp;               
    }
?>

[/code]

C++ 로 구현한 예
[code cpp]
#include <iostream>
using namespace std;

void swap(int *a , int *b)
{
    int *tmp = b;   
    b = a;
    a = tmp;
}

int main()
{
    int a[5] = {8 , 5 , 1 , 9 , 2};

    int loop_count = (sizeof(a) / sizeof(a[0])) - 1;
    bool flag = false;   
   
    do{       
        flag = false;
       
        for(int i = 0 ; i < loop_count ; i++)
        {
            if(a[i] > a[i +1])
            {
                swap(a[i] , a[i + 1]);
                flag = true;
            }
        }
                   
    }while(flag);   
   
    return 0;
}
[/code]

2010년 2월 17일 수요일

Windows에서 Ubuntu 9.10 로! #5

# 우분투 9.10을 처음 시작하게 되면 가독성 때문에 다소 애를 먹을 수가 있습니다. 이때 폰트를 설정해야 하는데 윈도우즈에 익숙한 우리에게 맞는 기본 폰트는 존재하지 않더군요.

그래서 공개용 글꼴

네이버 사전체 를 사용해야 합니다. (혹은, 기타 공개 폰트들)


네이버 사전체를 다운로드 받으셨다면 아마도 ~/다운로드 폴더에 존재하지 않을까 합니다.(기본 FF로 다운로드를 받으셨다면 말이죠)

일단 압축을 해제 합니다. 파일 브라우저에서 더블 클릭하셔도 되며 , 터미널에서 다음 명령어를 치셔도 됩니다.

cd ~/다운로드
tar xzvf naverdic.tgz

그럼 압축이 풀리면서 naverdic.ttf 파일이 하나 튀어나옵니다.

요 파일을 시스템에서 사용할 수 있게 옮겨야 합니다.
별다른 설정은 없고 단지 관리자 권한으로 해당 폴더에 넣으시면 됩니다.

일단 파일을 좀더 쉽게 관리하기 위해서 /usr/share/fonts/truetype/ 에 ttf-naverdic 이라는 폴더를 만들고 그곳에 파일을 옮기도록 하겠습니다.

sudo mkdir /usr/share/fonts/truetype/ttf-naverdic
sudo mv ~/다운로드/naverdic.ttf /usr/share/fonts/truetype/ttf-naverdic/naverdic.ttf

자 여기 까지하셨다면 성공입니다.

그럼 글꼴을 변경하도록 해보겠습니다.

글꼴 변경은 시스템 -> 기본 설정 -> 모양새 -> 글꼴 탭 에서 할 수 있습니다.



자 그럼 그런데 이상하게도 파이어폭스에서의 폰트를 변경되지 않는군요.
그럼 파이어폭스의 기본 글꼴도 변경하도록 하지요.

파이어폭스를 키시고

편집 -> 환경설정 -> 내용 탭으로 가시면 글꼴을 변경하실 수 있습니다.






Windows에서 Ubuntu 9.10 로! #4

#1. 이제 그래픽 드라이버도 잘 깔아놨으니 그래픽 드라이버를 십분 활용해봐야겠지요?

많이들 아시겠지만, 리눅스는 윈도우보다 좀더 역동적인 화면효과를 줄 수 있습니다. 어찌보면 윈도우 7 도 울고갈 정도로 아주 멋진 기능이지요. 아~ 물론 안전성이나 성능에서도 큰 문제는 없습니다. (간혹 버그가 보이긴 하지만요 ^^;;;)

우분투 9.10 에서는 기본적으로 compiz가 설치되어있습니다. 자 그런데 이 compiz란 놈이 무얼 하는 녀석이냐~ 이놈의 화면 효과를 주는 놈이지요.

아주 간단하게 맛보기를 하시려면

시스템 -> 기본 설정 -> 모양새 -> 화면 효과 -> 많이 체크

이렇게 해보시면 화면이 많이 ~~ 멋있어졌다라는 것을 느끼실 겁니다.


물론 효과가 많으면 많을 수록 시스템 자원을 많이 잡아먹는건 당연하니 시스템 사양에 맞게 적절한 선택을 해주어야 겠지만.

#2. 하지만 이것으로도 불편할 때가 있습니다. 왜냐하면 세세한 설정을 할 수 없기 때문이지요. 게다가 어떤 효과가 있는지도 모르니, 좀더 커스터마이징 해보고 싶은데 하질 못하게 된다면 좀 서운할 것 같네요.

그럴때 이 compiz를 관리해주는 매니져를 설치해야 합니다.

시스템 -> 관리 -> 시냅틱 패키지 관리자 -> 빠른 검색에 -> compiz-settings-manager

체크 하고 설치~~


자 설치 하고 나면 해당 관리자는 다음과 같은 경로에서 실행시킬 수 있습니다.

시스템 -> 기본설정 -> 컴피즈 설정 관리자



이리저리 둘러보시면서 체크를 하여 여러가지 효과를 설정할 수 있습니다. 아이콘을 클릭하면 해당 효과를 세부적으로 설정할 수 있지요.

예를 들어서 단축키를 다르게 설정한다던지, 혹은 효과의 duration을 설정한다던지 등등말이죠.

2010년 2월 9일 화요일

OSX 사용기...

iPhone 어플리케이션 개발을 위하여 회사에서 거금(?)을 투자하여 iMac을 구입하게되었다.

뭐 일단은 iPhone Developer 인증 진행중이라 아직 SDK를 깔아서 플밍을 시작하지는 않아 이것저것 만지작 만지작 거리며 구경하게 되었는데...

아... 정말이지...

Linux(gnome , KDE) , Windows 시리즈 모두 사용해보았지만...
나에게는 왜이렇게 Mac이 불편하기만 할까...

이것저것 만지면 일단 키보드 레이아웃 부터 적응을 다시 해야 하기 때문에 여러가지 불편한점이 한두개가 아니다...

더군다가 파워유저가 되려면 이것저것 많은 설정을 해야 하는데 아직은 경험도 없고...

초딩때 애플컴퓨터(그때 당시 아마 8 bit 였떠랬죠?) 만저본 이후 처음이라 그런가... ㅋㅋㅋ

아무튼, 새로운 것을 접하게 된 계기는 무척이나 좋았다만
글쎄다... 나의 새로운 지식 습득의 열정이 한풀 꺽였는지... 왠지 이놈은 다시는 거들떠 보고 싶지도 않을 정도다...

하지만 iPhone 어플 개발을 위해서 어쩔 수 없이 이놈과 친해져야 하다니...

이거.. 근데.. 스크린샷 어떻게 찍는거야 도대체 ... -_-;;; 이노무 애플...


-- 아 찾았따... -_-;;;

2010년 2월 5일 금요일

페이징 클래스

페이징 클래스 짜기가 귀찮아서 웹서핑을 하는 도중 2008년도에 내가 만든 소스를 발견.......

이런 우연이... -_-;;; 후덜덜...

아무튼, 자료를 한곳으로 모으기로 하였으니 이곳에 모아두어야 겠당.

[code java]
/*
 * Author : Mikelim(mikelim@ciyah.com)
 *
 * Pagination Class
 *
 * @properties
 *         firstLink , prevLink, nextLink , lastLink : set up image or text if you want.
 *         delimiter : set up image or text
 *         prewrap , postwrap : currentPage design wrapper tag
 */

public class Pagination {

    private int totalRows = 0;
    private int currentPage = 1;
    private int pageSize = 10;
    private int blockSize = 10;   
    private int totalPages;
    private int totalBlocks;
    private int startPageNum;
    private int endPageNum;
    private int currentBlock;

    private String amp = "";
   
    // for design
    public String firstLink = "[<<]";
    public String firstOffLink = "";
    public String prevLink = "[<]";
    public String prevOffLink = "";
    public String nextLink = "[>]";
    public String nextOffLink = "";
    public String lastLink = "[>>]";
    public String lastOffLink = "";
   
    public String delimiter = "|";
   
    // current Page Wrapper
    public String preWrap = "<b>";
    public String postWrap = "</b>";
   
    public String linkPage = "";
    public String queryString = "";
   
    // result temp object
    public StringBuffer pageString = new StringBuffer();
   
    public Pagination(int currentPage , int pageSize , int blockSize , int totalRows)
    {
        this.currentPage = currentPage;
        this.pageSize = pageSize;
        this.blockSize = blockSize;
        this.totalRows = totalRows;
       
        initialize();
    }
   
    public void initialize()
    {   
        this.totalPages = (int)Math.ceil((double)this.totalRows / this.pageSize);
        this.totalBlocks = (int)Math.ceil((double)this.totalPages / this.blockSize);
        this.currentBlock = (int)Math.ceil((double)((this.currentPage - 1) / this.blockSize)) + 1;       
        this.startPageNum = ((this.currentBlock - 1) * this.pageSize) + 1;
        this.endPageNum = this.startPageNum + this.pageSize;
    }
   
    public void prePrint()
    {
        // set first block link
        if(this.currentBlock > 1)
            pageString.append("<a href=\"" + this.linkPage + "?" + this.queryString + this.amp + "pg=" + (((this.currentBlock - 2) * this.pageSize) + 1) + "\">" + this.firstLink + "</a> ");
        else
            pageString.append(this.firstOffLink + " ");
           
       
        // set prev page link
        if(this.currentPage > 1)
            pageString.append("<a href=\"" + this.linkPage + "?" + this.queryString + this.amp + "pg=" + (this.currentPage  - 1) + "\">" + this.prevLink + "</a> ");
        else
            pageString.append(this.prevOffLink + " ");       
    }
   
    public void postPrint()
    {
        // set next page link
        if(this.currentPage < this.totalPages )
            pageString.append("<a href=\"" + this.linkPage + "?" + this.queryString + this.amp + "pg=" + (this.currentPage + 1) + "\">" + this.nextLink + "</a> ");
        else
            pageString.append(this.nextOffLink + " ");
       
        // set last page link
        if(this.currentBlock < this.totalBlocks)
            pageString.append("<a href=\"" + this.linkPage + "?" + this.queryString + this.amp + "pg=" + ((this.currentBlock * this.pageSize) + 1) + "\">" + this.lastLink + "</a> ");
        else
            pageString.append(this.lastOffLink);
    }
   
    public void printList()
    {   
        for(int i = startPageNum ; i <= endPageNum ; i++)
        {
            if(i > this.totalPages || i == endPageNum)
                break;
            else if(i > startPageNum)
                pageString.append(this.delimiter);
           
            if(i == this.currentPage)           
                pageString.append(" " + this.preWrap + i +  this.postWrap + " ");
            else
                pageString.append(" <a href=\"" + this.linkPage + "?" + this.queryString + this.amp + "pg=" + i + "\">" + i + "</a> ");
        }
    }
   
    public String print()
    {
        // set amp if already to set up queryString property
        if(!this.queryString.equals(""))
            this.amp = "&";
       
        if(this.totalPages > 1)
        {
            this.prePrint();
            this.printList();
            this.postPrint();
        }
       
        return(pageString.toString());
    }
   
    /**
     * @param args
     */
    /*
    public static void main(String[] args) {
       
        // TODO Auto-generated method stub
        Pagination pg = new Pagination(20 , 10, 10 , 352);
        pg.linkPage = "pagenum.jsp";
        pg.queryString = "param1=test&param2=test2";
       
        // for design
        pg.firstLink = "<img src=\"/first.gif\">";
        pg.prevLink = "<img src=\"/prev.gif\">";
        pg.nextLink = "<img src=\"/next.gif\">";
        pg.lastLink = "<img src=\"/last.gif\">";
       
        pg.delimiter = "|";
       
       
        //print
        System.out.println(pg.print());
    }
    */

}
[/code]

소스파일은 첨부~~