Codebreaker 2bc08752a0894eb2c7afb345286e391d

14Feb/103

한자-한글 변환

오랜만의 한국어 포스팅이다.

나는 어렸을 때 한자 공부를 열심히 하지 않아서 그런지, 이런 글을 보면 무언가 거부감이 든다. 한자와 한글의 병용을 주장하는 글을 한자 혼용으로 작성해놓은 이유는 무엇인가.

본문에 따르자면 한자를 배워야 하는 이유를 다음의 몇가지로 요약할 수 있다.

  1. 성명의 한자 표기를 통해 자기의 근본을 알고 자기 정체성을 확립한다.
  2. 어휘력을 풍부하게 한다.
  3. 단어의 뜻을 명확하게 알 수 있다.

먼저, 자기의 성과 이름을 한자로 쓸 줄 알고 자기의 근본을 알고 자기정체성을 확립하는 것과 일상 생활에서 한자를 병용하는것은 별 관계가 없어보인다. 또, 흔한 경우는 아니지만, 한글 전용으로 인해 특정 단어의 의미가 명확하지 않은 경우가 있을수도 있는데, 이런 경우에 한해서만 괄호 안에 대응되는 한자를 넣어주는 한자 병용으로 문제를 해결할 수 있다. 대부분의 경우에 한글 전용으로도 의미가 확실히 전달되는데에도 불구하고 굳이 한자를 쓰는것은 대단한 자원의 낭비라고 생각된다.

본문 중에 다음과 같은 내용이 있다.

例를 들어 여기 흔히 쓰이는 정신 나간 사람이라고 할 때 ‘井神, 定身, 廷臣, 精神, 挺身, 正信, 貞臣, 淨神, 正身, 情神, 鼎臣’ 등이 있는데 이 중 어느 정신인지 漢字를 모르면 구분이 잘 안 된다.

주장하고자 하는 바가 무엇인지 대략 짐작이 가지만, 예를 조금 잘못 선택한것 같다. 위의 문맥에서 쓰인 '정신'이 어떤 뜻의 정신인지 모르면 정말로 정신 나간 사람이 아닐까 한다.

이것 이외에도 적절하지 않은 뒷받침 내용이나, 출처나 사실 여부를 알 수 없는 서술문, 논리적 오류가 보이지만, 이 글을 쓰는 목적이 위의 글을 비판하기 위함이 아니므로 본론으로 넘어가도록 하겠다.

오늘 이 글을 쓰는 목적은 한자-한글 변환기를 공개하는 것이다. 이것 덕분에 위의 한자 혼용 글도 읽고 이해할 수 있었다.

일단, 약 3만개의 한자-한글 매핑 데이터를 여기서 얻어왔다. 이것을 파이썬의 사전(dictionary) 형식으로 표현하고, 변환할 문자열에서 한 글자씩 한자에서 한글로 변환하는 방식이다. 핵심 기능을 하는 코드는 다음의 한 줄이 전부이고, 나머지는 사용자의 입력을 받고 결과물을 보여주기 위한 코드이다.

map(lambda x: x in dict and dict[x] or x, post['query'])

map 함수가 어떤 기능을 하는 것인지 모르겠으면 이 문서를 읽어보길 바란다. map, reduce, filter 과 같은 higher-order function 들을 잘 쓰면 프로그램을 간결하면서도 효과적으로 작성할 수 있다.

4Feb/101

Programming Contest: 4-function Calculator

Today's programming contest, sponsored by Jude Nelson, was to make a 4-function calculator using PyMT. There were some extra credits for additional features such as support for trigonometric functions, parenthesis for changing orders of operations, and so on.

Even though I was the winner (thanks to Google), I admit I wrote an embarrasingly low quality code, but I think I have legitimate excuses; I've never dealt with PyMT until few hours ago, and we had a very tight time constraint.

So, here I'm posting the full source code at the request of Charles and a couple more people.

import urllib, urllib2, re
from pymt import *

# Google search would give me a 403 error so I had to "pretend" to be a real web browser.
useragent = 'Mozilla/5.0 (X11; U; Linux x86_64; fr; rv:1.9.1.6) Gecko/20091215 Ubuntu/9.10 (karmic) Firefox/3.5.6'

# This is how you get things done.
url = 'http://www.google.com/search?'

m = MTWidget()

button0 = MTButton(label='0', pos=(0, 0), size=(90, 90))
buttonpr = MTButton(label='.', pos=(100,0), size=(90, 90))
buttonok = MTButton(label='=', pos=(200,0), size=(90, 90))

button1 = MTButton(label='1', pos=(0,100), size=(90, 90))
button2 = MTButton(label='2', pos=(100,100), size=(90, 90))
button3 = MTButton(label='3', pos=(200,100), size=(90, 90))

button4 = MTButton(label='4', pos=(0,200), size=(90, 90))
button5 = MTButton(label='5', pos=(100,200), size=(90, 90))
button6 = MTButton(label='6', pos=(200,200), size=(90, 90))

button7 = MTButton(label='7', pos=(0,300), size=(90, 90))
button8 = MTButton(label='8', pos=(100,300), size=(90, 90))
button9 = MTButton(label='9', pos=(200,300), size=(90, 90))

m.add_widget(button0)
m.add_widget(buttonpr)
m.add_widget(buttonok)
m.add_widget(button1)
m.add_widget(button2)
m.add_widget(button3)
m.add_widget(button4)
m.add_widget(button5)
m.add_widget(button6)
m.add_widget(button7)
m.add_widget(button8)
m.add_widget(button9)

buttonlp = MTButton(label='(', pos=(400,0), size=(90, 90))
buttonrp = MTButton(label=')', pos=(500,0), size=(90, 90))

m.add_widget(buttonlp)
m.add_widget(buttonrp)

buttonp = MTButton(label='+', pos=(300,300), size=(90, 90))
buttons = MTButton(label='-', pos=(300,200), size=(90, 90))
buttonm = MTButton(label='*', pos=(300,100), size=(90, 90))
buttond = MTButton(label='/', pos=(300,0), size=(90, 90))

m.add_widget(buttonp)
m.add_widget(buttons)
m.add_widget(buttonm)
m.add_widget(buttond)

buttonbs = MTButton(label='<-', pos=(400,100), size=(90, 90))
buttoncl = MTButton(label='CL', pos=(400,200), size=(90, 90))

m.add_widget(buttonbs)
m.add_widget(buttoncl)

buttonsin = MTButton(label='sin', pos=(500,300), size=(90, 90))
buttoncos = MTButton(label='cos', pos=(500,200), size=(90, 90))
buttontan = MTButton(label='tan', pos=(500,100), size=(90, 90))

m.add_widget(buttonsin)
m.add_widget(buttoncos)
m.add_widget(buttontan)

buttonhex = MTButton(label='0x', pos=(600,0), size=(90, 90))
buttonbin = MTButton(label='0b', pos=(600,100), size=(90, 90))

m.add_widget(buttonhex)
m.add_widget(buttonbin)

inputl = MTLabel(label='', pos=(0, 400), size=(90, 300))
m.add_widget(inputl)

#@button0.event
#def on_press(*largs):
#   print 'on_press()', button0.state, largs

@button0.event
def on_release(*largs):
    inputl.label += '0'

@button1.event
def on_release(*largs):
    inputl.label += '1'

@button2.event
def on_release(*largs):
    inputl.label += '2'

@button3.event
def on_release(*largs):
    inputl.label += '3'

@button4.event
def on_release(*largs):
    inputl.label += '4'

@button5.event
def on_release(*largs):
    inputl.label += '5'

@button6.event
def on_release(*largs):
    inputl.label += '6'

@button7.event
def on_release(*largs):
    inputl.label += '7'

@button8.event
def on_release(*largs):
    inputl.label += '8'

@button9.event
def on_release(*largs):
    inputl.label += '9'

@buttonlp.event
def on_release(*largs):
    inputl.label += '('

@buttonrp.event
def on_release(*largs):
    inputl.label += ')'

@buttonp.event
def on_release(*largs):
    inputl.label += '+'

@buttons.event
def on_release(*largs):
    inputl.label += '-'

@buttonm.event
def on_release(*largs):
    inputl.label += '*'

@buttond.event
def on_release(*largs):
    inputl.label += '/'

@buttonpr.event
def on_release(*largs):
    inputl.label += '.'

@buttonbs.event
def on_release(*largs):
    inputl.label = inputl.label[:-1]

@buttoncl.event
def on_release(*largs):
    inputl.label = ''

@buttonsin.event
def on_release(*largs):
    inputl.label += 'sin('

@buttoncos.event
def on_release(*largs):
    inputl.label += 'cos('

@buttontan.event
def on_release(*largs):
    inputl.label += 'tan('

@buttonhex.event
def on_release(*largs):
    inputl.label += '0x'

@buttonbin.event
def on_release(*largs):
    inputl.label += '0b'

@buttonok.event
def on_release(*largs):
    inputl.label = get_result(inputl.label)

def get_result(query):
    headers = {'User-Agent':useragent}
    req = urllib2.Request(url + urllib.urlencode({'q':query}), None, headers)
    r = urllib2.urlopen(req)
    result = r.read()

    m1 = re.search('<td nowrap ><h2 class=r style="font-size:138%"><b>', result)
    if m1 is None:
        return 'Invalid expression'

    m2 = re.search('</b>', result[m1.end():])

    return result[m1.end():(m1.end()+m2.start())]


runTouchApp(m)
Tagged as: , , 1 Comment
12Sep/093

Future Project: OpenOffice for Mac

Thoughts

Mac applications in general have been maintaining a pretty good consistency in terms of user interface/experience. In case of Windows or Linux applications, it is not a big of deal to be inconsistent because either there is no concrete guideline that states how applications should look and how they behave, or no one really cares what the guideline suggests. However, in case of Mac applications, it really makes your application distinguishable, usually in a bad way, if you don't follow the guide line. Our popular example would be the OpenOffice application suite.

OpenOffice Writer

Screen shot 2009-10-12 at 2.14.04 AM

I have no doubt that OpenOffice is a great application and I use it on my Linux workstation, but let's face it. It's ugly.

Apple iWork Pages

Screen shot 2009-10-12 at 2.09.49 AM

Yup. I actually paid for this ;-)

What I Want To Do

So, what I want to do is to make a decent user interface for OpenOffice, using the Cocoa framework, to give it a consistent look and feel and common behaviors provided by the Cocoa framework so that it looks like a typical Mac application.

It's going to be a lot of work even though significant amount of code base of the OpenOffice remains unchanged. If you have skills and time, please jump in to this. I won't mind for you to steal my idea. I would love to see what comes out.

Tagged as: , , 3 Comments