U E D R , A S I H C RSS

Self-describing Sequence/1002

approach

1μ°¨ μ‹œλ„

λŒ€λž΅ μ—°μŠ΅μž₯에 μˆ˜μ—΄μ΄ λ§Œλ“€μ–΄μ§ˆ λͺ¨μŠ΅μ„ μƒκ°ν•˜λ©΄μ„œ λ””μžμΈ, 20λΆ„ 정도 μ½”λ”©.


~cpp
def selfDescrib(n):
    table = [1,2,2]
    e=2
    while e!=n+1:
        e+=1
        table += [e] * table[e-1]
        if len(table) > n-1:
            return table[n-1]

for i in [100,9999,123456,1000000000]: print selfDescrib(i)

2μ°¨ μ‹œλ„

λ¬Έμ œλŠ”, 1000000000 의 κ²½μš°μ— λŒ€ν•΄μ„œ 닡이 λ‚˜μ˜€λŠ” μ‹œκ°„μ΄ μ—„μ²­λ‚˜κ²Œ κ±Έλ¦°λ‹€λŠ” 점이닀. 이에 λŒ€ν•΄μ„œ μ–΄λ–»κ²Œ ν•  것인가 κ³ λ―Ό,
μ—¬λŸ¬ 접근법에 λŒ€ν•΄μ„œ μƒκ°ν•˜κ²Œ 됨.
  • μˆ˜μ—΄μ— λŒ€ν•œ μΌλ°˜μ‹μ΄ μžˆμ„κΉŒ?
  • k κ°’ λŒ€λΉ„ f(k) 값을 훨씬더 많이 μ•Œμ•„λ‚Ό 수 μžˆμ„ν…λ°, 이λ₯Ό μ΄μš©ν•  방법이 μžˆμ„κΉŒ?
그와 κ΄€λ ¨ν•˜μ—¬ ν”„λ‘œκ·Έλž˜λ°μ„ μ§„ν–‰ν•΄λ³΄μ•˜μœΌλ‚˜ 그리 μ„±κ³Όκ°€ μ—†μŒ.

3μ°¨ μ‹œλ„

μ–΄μ œμ— μ΄μ–΄μ„œ κ³ λ―Όν•˜λ˜ 쀑, λ¬Έμ œμ μ— λŒ€ν•΄μ„œ λ‹€μ‹œ 생각. 결ꡭ은 f(k) λ₯Ό μœ„ν•œ table μƒμ„±μ—μ„œ λ©”λͺ¨λ¦¬λ₯Ό 많이 μ“΄λ‹€λŠ” 점이 문제.
이에 λŒ€ν•΄μ„œ λ‹€λ΄κ²Œ representation ν•  방법을 μƒκ°ν•˜λ‹€κ°€ λ‹€μŒκ³Ό 같이 representation ν•  방법을 λ– μ˜¬λ¦¬κ²Œ 됨.
f(1) : 1
f(2) ~ f(3) : 2
f(4) ~ f(5) : 3
f(6) ~ f(8) : 4
f(9) ~ f(11) : 5
.
.

이에 λŒ€ν•΄μ„œ λ‹€μŒκ³Ό 같이 κ΅¬ν˜„
~cpp
# ν•΄λ‹Ή 숫자 λ²”μœ„λ₯Ό μ‘°μ‚¬ν•˜μ—¬ μ–΄λ–€ 값이 λ‚˜μ˜¬μ§€λ₯Ό return
def findGroupIdx(table,n,startPos=0):
	for i in xrange(len(table)):
		x,y=table[i]
		if x<=n<=y: return i+1

def selfDescrib2(n):
    table=[(1,1),(2,3)]
    if n==1 or n==2: return n

    for i in xrange(3,n+1):
        start = table[-1][-1] + 1
        theGroupIdx = findGroupIdx(table,i)
        repeat = theGroupIdx
        end = start + repeat - 1
        table.append((start,end))
        if start >= n:
            return findGroupIdx(table,n)

ν’€κ³  λ‚˜λ‹ˆ, κ·Έλž˜λ„ μ—­μ‹œ 1000000000 에 λŒ€ν•΄μ„œλŠ” ꡉμž₯히 느림. 느릴 뢀뢄을 μƒκ°ν•˜λ˜ 쀑 findGroupIdx 뢀뢄이
λ¬Έμ œμž„μ„ 생각. 이λ₯Ό binary search κ΅¬ν˜„μœΌλ‘œ λ°”κΏˆ.
~cpp
def findGroupIdx(table,n,startPos=0):
    midIdx = len(table)/2
    mid = table[midIdx]
    x,y=mid
    if x<=n<=y: return midIdx+1+startPos
    if n<x: return findGroupIdx(table[:midIdx],n,startPos)
    else: return findGroupIdx(table[midIdx+1:],n,startPos+midIdx+1)

binary search 둜 λ°”κΎΈκ³  λ‚˜μ„œλ„ μ—­μ‹œ 였래걸림. λ‹€λ₯Έ 검색법에 λŒ€ν•΄μ„œ μƒκ°ν•˜λ˜ 쀑, findGroupIdx ν•¨μˆ˜ ν˜ΈμΆœμ„ ν• λ•Œλ₯Ό 생각.
μˆ˜μ—΄μ˜ 값이 늘 μ¦κ°€ν•œλ‹€ ν• λ•Œ λ‹€μŒλ²ˆμ— κ²€μƒ‰ν•˜λŠ” 경우 μ•žμ—μ„œ κ²€μƒ‰ν–ˆλ˜ κ·Έλ£Ή μ•„λ‹ˆλ©΄ κ·Έ λ‹€μŒ κ·Έλ£Ήμž„μ„ μƒκ°ν•˜κ²Œ 됨.
~cpp
class FindGroupIdxs:
    def __init__(self,table):
        self._table = table
        self._prevSearchPos = 0
    def find(self,n):
        while True:
            x,y=self._table[self._prevSearchPos]
            if x<=n<=y: return self._prevSearchPos+1
            self._prevSearchPos+=1

def selfDescrib2(n):
    table=[(1,1),(2,3)]
    if n==1 or n==2: return n

    finder = FindGroupIdxs(table)

    for i in xrange(3,n+1):
        start = table[-1][-1] + 1
        theGroupIdx = finder.find(i)
        repeat = theGroupIdx
        end = start + repeat - 1
        table.append((start,end))
        if start >= n:
            return finder.find(n)

def main():
    import time
    for e in [100,9999,123456,1000000000]: 
        start=time.time()
        print e,selfDescrib2(e)
        print "time : ", time.time()-start

import psyco
psyco.full()
main()

μˆ˜ν–‰ μ‹œκ°„ : 1000000000 κΈ°μ€ 0.95초(with psyco) 2.18초(without psyco)
λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰ : 31MB

λŠλ‚Œ

  • μ§€μ†μ μœΌλ‘œ 퍼포먼슀 νŠœλ‹μ„ μœ„ν•΄ λ‹€λ₯Έ μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ 접근을 ν•΄λ³Έ 점이 μ’‹μ•˜μŒ.
  • ν•˜μ§€λ§Œ, μˆ˜ν•™μ μΈ 관계λ₯Ό μ°Ύμ•„λ‚΄λŠ”λ°μ—λŠ” μ—­μ‹œ ν•œκ³„λ₯Ό λ³΄μž„. κ·ΈλƒνΌν¬λ¨ΌμŠ€ ν–₯상을 μœ„ν•œ μ•Œκ³ λ¦¬μ¦˜ κ°œμ„ λ²•μœΌλ‘œλ§Œ μ ‘κ·Ό.
    λ„ˆλ¬΄ μ§κ΄€μ—λ§Œ 의μ΄ν•˜μ—¬ ν‘Ό 점이 아쉽긴 함.
  • λ‹€μ‹œκΈˆ '이 λ¬Έμ œμ—μ„œ μš”κ΅¬ν•œ 방법이 이 λ°©λ²•μ΄μ˜€μ„κΉŒ?' 에 λŒ€ν•΄μ„œ κ³ λ―Όν•˜κ²Œ 됨. 비둝 μ›ν•˜λŠ” μ„±λŠ₯은 λ‚˜μ˜€κΈ΄ ν–ˆμ§€λ§Œ.
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:28:00
Processing time 0.0214 sec