algorithm self describing sequence - andstudy/forge GitHub Wiki

Mastojun

문제 풀이

  • μ‰¬μš΄λ¬Έμ œμΈμ€„ μ•Œμ•˜λŠ”λ°, 썩 μ‰¬μš΄κ±΄ μ•„λ‹ˆλ”κ΅°μš”. 숫자 λ²”μœ„κ°€ κ°€μž₯ 큰 걸림돌 μ΄μ˜€μŠ΅λ‹ˆλ‹€.
  • μ΅œλŒ€ μž…λ ₯값이 20μ–΅ 이기 λ•Œλ¬Έμ— 20μ–΅μ˜ 배열에 각각의 κ²°κ³Όλ₯Ό 미리 κ΅¬ν•΄λ‘λŠ” λ°©λ²•μœΌλ‘œ μ²˜μŒμ— μ ‘κ·Ό ν–ˆμœΌλ‚˜ λ°°μ—΄μ˜ 크기가 0xffffffffλ₯Ό λ„˜μ—ˆκΈ° λ•Œλ¬Έμ— 컴파일 μ—λŸ¬.
  • 배열을 λ‘κ°œλ‘œ μͺΌκ°œμ„œ ν•΄λ³΄μ•˜μ§€λ§Œ μŠ€νƒ μ˜μ—­μ΄ μ œν•œμ΄ λ„˜μ–΄μ„œ μ—λŸ¬.
  • 사싀 이건 컴파일 μ„±κ³΅ν•˜λ”λΌλ„ μ‹€ν–‰μ‹œκ°„μ΄ 맀우 크기 λ•Œλ¬Έμ— (일반적으둜 Big-O 둜 ν‘œν˜„ν–ˆμ„λ•Œ μ΅œλŒ€κ°’μ— λŒ€ν•œ κ²°κ³Όκ°€ 1얡이 λ„˜μœΌλ©΄ μ‹œκ°„μ΄ˆκ³Όκ°€ λ–¨μ–΄μ§‘λ‹ˆλ‹€, 10μ–΅μ΄μ˜€λ‚˜;) λΆˆκ°€λŠ₯ν•œ λ°©λ²•μ΄μ˜€μŠ΅λ‹ˆλ‹€.
  • 결ꡭ에 μ—­μœΌλ‘œ 생각을 ν–ˆμŠ΅λ‹ˆλ‹€. 1이 μ‹œμž‘ν•˜λŠ” 숫자, 2κ°€ μ‹œμž‘ν•˜λŠ” 숫자, 3이 μ‹œμž‘ν•˜λŠ” 숫자, μ΄λŸ°μ‹μœΌλ‘œ μ €μž₯ν•˜λ©΄ λ°°μ—΄μ˜ 크기λ₯Ό 맀우 많이 κ°μ†Œμ‹œν‚¬ 수 μžˆκ±°λ“ μš”.
  • ν•˜μ§€λ§Œ 이 방법도 ν•¨μˆ˜ 내뢀에 있으면 μŠ€νƒν¬κΈ° 초과둜 컴파일 μ•ˆλ˜λ”κ΅°μš”, κ·Έλž˜μ„œ μ „μ—­μœΌλ‘œ λ‘μ—ˆμŠ΅λ‹ˆλ‹€.
  • μ—¬ν•˜νŠΌ.... νž˜λ“€κ²Œ Solvedλ°›μ•˜λ„€μš”

μ†ŒμŠ€ μ½”λ“œ

    #include <iostream>
    using namespace std;
    
    int Set[1000000];
    
    int main()
    {
    
    	Set[1] = 1;
    	Set[2] = 2;
    	Set[3] = 4;
    	Set[4] = 6;
    	Set[5] = 9;
    
    	int remember = 1;
    	for( int i = 6; i < 1000000; i++ )
    	{
    		int Temp = Set[i-1];
    		int j;
    
    		for( j = remember; j < i; j++ )
    		{
    			if( Set[j+1] >= i ) break;
    		}
    
    		Set[i]	 = Temp + j;
    		remember = j;
    	}
    
    	int in;
    
    	while( cin >> in )
    	{
    		if( in == 0 ) break;
    
    		int i;
    
    		for(i = 1; i < 1000000; i++ )
    		{
    			if( Set[i+1] > in ) break;
    		}
    
    		cout << i << endl;
    	}
    
    	return 0;
    }

CynicJJ

  • μ΅œμ’…μ μœΌλ‘œλŠ” λͺ‡μ€„ μ•ˆλ˜λŠ” μ½”λ“œμ§€λ§Œ μ—„μ²­ κ³ μƒν–ˆμŠ΅λ‹ˆλ‹€.
  • 섀계도 λ‘λ²ˆμ΄λ‚˜ λ’€μ§‘μ—ˆκ³ μš”.
  • TDD도 잘 μ•ˆλ˜μ„œ 고치고 μ‹€ν–‰ν•˜κ³  고치고 μ‹€ν–‰ν•˜κ³  λ°˜λ³΅μ— λŠͺ에 λΉ μ§„ κΈ°λΆ„μ΄μ—ˆμŒ.
  • 큰 수 μΌλ•Œ μ„±λŠ₯이 μ’€ λ–¨μ–΄μ§€λ„€μš”.

!SelfDescribingSequence.vb

    ' $Id: SelfDescribingSequence.vb 121 2008-03-04 05:18:53Z 정희쒅 $
    
    Public Class SelfDescribingSequence
    
    	Private _sequence As Dictionary(Of Integer, Integer) = New Dictionary(Of Integer, Integer)
    
    	Function GetValue(ByVal k As Integer) As Integer
    		Dim key As Integer = 1
    		Dim value As Integer = 1
    
    		While True
    			If Not _sequence.ContainsKey(key) Then
    				_sequence.Add(key, value)
    			End If
    
    			key = key + GetValueCount(value)
    			If key > k Then Exit While
    			value = value + 1
    		End While
    
    		Return value
    	End Function
    
    	Private Function GetValueCount(ByVal value As Integer) As Integer
    		While Not _sequence.ContainsKey(value)
    			value -= 1
    		End While
    		Return _sequence(value)
    	End Function
    End Class

!SelfDescribingSequenceTest.vb

    <TestClass()> _
    Public Class SelfDescribingSequenceTest
    	<TestMethod()> _
    	Public Sub GetValueTestInit()
    		Dim sds As SelfDescribingSequence = New SelfDescribingSequence
    		Assert.AreEqual(1, sds.GetValue(1))
    		Assert.AreEqual(2, sds.GetValue(2))
    		Assert.AreEqual(2, sds.GetValue(3))
    	End Sub
    
    	<TestMethod()> _
    	Public Sub GetValueTestSmall()
    		Dim sds As SelfDescribingSequence = New SelfDescribingSequence
    		Assert.AreEqual(5, sds.GetValue(10))
    		Assert.AreEqual(8, sds.GetValue(22))
    	End Sub
    
    	<TestMethod()> _
    	Public Sub GetValueTestLarge()
    		Dim sds As SelfDescribingSequence = New SelfDescribingSequence
    		Assert.AreEqual(21, sds.GetValue(100))
    		Assert.AreEqual(356, sds.GetValue(9999))
    		Assert.AreEqual(1684, sds.GetValue(123456))
    	End Sub
    
    	<TestMethod()> _
    	Public Sub GetValueTestHuge()
    		Dim sds As SelfDescribingSequence = New SelfDescribingSequence
    		Assert.AreEqual(438744, sds.GetValue(1000000000))
    		Assert.AreEqual(673365, sds.GetValue(2000000000))
    	End Sub
    End Class

ParkPD

이게 무슨 μˆœμ—΄μΈμ§€ μ΄ν•΄ν•˜λŠ” λ°μ—λ§Œ 1μ‹œκ°„μ΄ 더 κ±Έλ Έλ„€μš”. 머리가 ꡳ은 κ±° κ°™μ•„ κ±±μ •μ΄μ˜ˆμš”.

    -- Library
    
    function fwrite(fmt, ...)
    	return io.write(string.format(fmt, unpack(arg)))
    end
    
    function swrite(fmt, ...)
    	return string.format(fmt, unpack(arg))
    end
    
    function SwapBySize(i1, i2)
    	if (i2 < i1) then
    		return i2, i1
    	end	
    	return i1, i2
    end
    
    function IsBetween(i, i1, i2)
    	i1, i2 = SwapBySize(i1, i2)
    	return i1 <= i and i <= i2
    end
    
    function PrintTable(t)	
    	fwrite("%s\n", ConvertTableToString(t))
    end
    
    function ConvertTableToString(t)
    	s = "["
    	for _, k in pairs(t) do
    		s = s..tostring(k)..' '
    	end
    	s = s .. "]"
    	return s
    end
    
    function pack(...)
    	return arg
    end
    
    function PushBackTable(t, a, n)
    	for _ = 1, n do
    		t[#t + 1] = a
    	end
    	return t
    end
    
    -- UnitTest
    UnitTest = {test = 0, success = 0, failed = 0}
    
    function UnitTest:new(o)
    	o = o or {}
    	setmetatable(o, self)
    	self.__index = self
    	return o
    end
    
    function UnitTest:ShowResult()
    	if UnitTest.failed == 0 then
    		fwrite("Success : %d tests passed\n", UnitTest.success)
    	else
    		fwrite("Failed : %d in tests %d\n", UnitTest.failed, UnitTest.test)
    	end
    end
    
    function Check(name, actual)
    	UnitTest.test = UnitTest.test + 1
    	if not actual then
    		fwrite("Check Failed in %s\n", name)
    		UnitTest.failed = UnitTest.failed + 1
    	else
    		UnitTest.success = UnitTest.success + 1
    	end
    end
    
    function CheckEqual(name, expect, actual)
    	UnitTest.test = UnitTest.test + 1
    	if (expect ~= actual) then
    		fwrite("CheckEqual Failed in %s. %s expected but actual is %s\n", name, tostring(expect), tostring(actual))
    		UnitTest.failed = UnitTest.failed + 1
    	else
    		UnitTest.success = UnitTest.success + 1
    	end
    end
    
    function CheckArrayEqual(name, expect, actual)
    	UnitTest.test = UnitTest.test + 1
    	
    	local fail = false
    	if (#expect == #actual) then
    		for k, v in pairs(expect) do
    			if (actual[k] ~= v) then
    				fail = true
    				break
    			end			
    		end		
    	else
    		fail = true
    	end
    		
    	if (fail) then
    		fwrite("CheckArrayEqual Failed in %s. %s expected but actual is %s\n", name, ConvertTableToString(expect), ConvertTableToString(actual))
    		UnitTest.failed = UnitTest.failed + 1
    	else
    		UnitTest.success = UnitTest.success + 1
    	end
    end
    
    -- Algorithm
    
    GSeq = {Nums = {1, 2}, k = 3, v = 3}
    function GSeq:new(o)
    	o = o or {}
    	setmetatable(o, self)
    	self.__index = self
    	return o
    end
    
    function GSeq:GetNearSeq(num)
    	for i = 0, num do
    		if (self.Nums[num - i] ~= nil) then
    			return self.Nums[num - i]
    		end
    	end
    	
    	assert(0)
    	return -1
    end
    
    -- k 의 μœ„μΉ˜λŠ” 아직 μˆœμ—΄μ„ λ§Œλ“€μ§€ μ•Šμ€ 졜초의 key λ₯Ό 가리킀고
    -- v 의 μœ„μΉ˜λŠ” λ°”λ‘œ 이전에 μ²˜λ¦¬ν•œ μˆœμ—΄μ˜ λ§ˆμ§€λ§‰ μœ„μΉ˜λ₯Ό 가리킨닀.
    -- 즉, λ‹€μŒ μˆœμ—΄μ€ k λΆ€ν„° μ‹œμž‘ν•˜κ³ , 
    -- k λΌλŠ” 숫자λ₯Ό v + 1 μœ„μΉ˜μ—μ„œλΆ€ν„° f(k) 만큼 μΆ”κ°€ν•΄ μ£Όλ©΄ λœλ‹€.
    function GSeq:GetF(num)
    	while (self.v < num) do
    		self.Nums[self.v + 1] = self.k
    		if (self.Nums[self.k] ~= nil) then
    			self.v = self.v + self.Nums[self.k]
    		else
    			-- λ°”λ‘œ 이전 녀석을 μ°ΎλŠ”λ‹€.
    			self.v = self.v + self:GetNearSeq(self.k)
    		end
    		
    		self.k = self.k + 1
    	end
    	
    	return self:GetNearSeq(num)
    end
    
    -- test part
    
    do
    	local t = {1, 2, 3}
    	local k = PushBackTable(t, 6, 2)
    	CheckArrayEqual("PushBackTable", {1, 2, 3, 6, 6}, k)
    end
    
    do
    	local testSet = 
    		{
    		  	4, 3,
    		  	5, 3,
    		  	6, 4,
    		  	7, 4, 
    		  	8, 4, 
    		  	9, 5
    		}
    
    	for i = 1, #testSet, 2 do
    		CheckEqual("GetF _ "..testSet[i], testSet[i + 1], GSeq:GetF(testSet[i]))
    	end	
    end
    
    do
    	CheckEqual("GetF 1", 21, GSeq:GetF(100))
    	CheckEqual("GetF 1", 356, GSeq:GetF(9999))
    	CheckEqual("GetF 1", 1684, GSeq:GetF(123456))
    	
    	-- 첫 λ°©λ²•μœΌλ‘œ ν–ˆμ„ λ•ŒλŠ” λ©”λͺ¨λ¦¬κ°€ λΆ€μ‘±ν•˜λ‹€κ³  λ‚˜μ™”λ‹€. λƒ ...
    	-- μ΄μ •ν‘œλ§Œ μ°μœΌλ©΄μ„œ μ§„ν–‰ν•˜μž.
    	CheckEqual("GetF 1", 438744, GSeq:GetF(1000000000))
    end
    
    UnitTest:ShowResult()
    
    -- input part
    
    while 1 do
    	local count = io.read("*number")
    	if count == nil then 
    		break 
    	end
    end
⚠️ **GitHub.com Fallback** ⚠️