2013-09-29 31 views
1

我令人難以置信的困惑。我試圖讓後面的模式這種模式存在一個程序:Python解決模式並用數字和英文單詞返回答案

Index: Value: 
0   0 
1   10 
2   1110 
3   3110 
4   132110 
5   1113122110 
6   311311222110 
... 

這種模式需要的功能的前值和說的數字,例如 的號碼,如果1號是10,2會說一一個和一個零或1110.

我做了一個函數,它接受一個字符串的第一個字符並返回該字符出現在字符串其餘部分的次數。我需要爲索引提示,然後它會打印出:

index : digits : english words 
3 : 3110 : three ones. one zero 

這是我到目前爲止的代碼,但我無法弄清楚如何解決實際值:

def strHead(s): 
    """strHead: String -> String""" 
    return s[0] 

def strTail(s, run): 
    """strTail: String -> String""" 
    return s[1:] 

def runLenAux(s, c): 
""" s = string and c = head of string 
""" 
    if s == "": 
     return 0 
    else: 
     if strHead(s)== c: 
      return 1 + int(runLenAux(strTail(s), c)) 
     else: 
      return 0 

編輯: 不幸的是我不能使用像.append或len()這樣的內置函數,我甚至不能使用列表。 :(有沒有辦法將我的函數runLenAux(s,c)找到值,如果給定索引?

+0

請注意,您的'strTail'返回整個字符串's'的一個副本。要返回's'的尾部(除第一個字符外的所有內容),請使用's [1:]'。 –

回答

3

這主要是以itertools.groupby的形式寫給你的,它需要一個迭代器(在你的情況下,字符串)並對獨特的元素進行分組,它給出了一個生成器(認爲它是一個你可以循環的列表,如果你不熟悉它們的話),其中每一對都是你原始迭代的值,然後所有這些值

因此,舉例來說:

>>> s = str(1113122110) 
>>> groupby(s) 
<itertools.groupby at 0x1044be5d0> 

讓我們把它們列出來一飽眼福:

>>> [(n, list(c)) for n, c in groupby(s)] 
[('1', ['1', '1', '1']), 
('3', ['3']), 
('1', ['1']), 
('2', ['2', '2']), 
('1', ['1', '1']), 
('0', ['0'])] 

要進入你想要的格式,這一點,你真的希望每個二級列表的長度:

>>> [(len(list(c)), n) for n, c in groupby(s)] 
[(3, '1'), (1, '3'), (1, '1'), (2, '2'), (2, '1'), (1, '0')] 

讓我們把長度字符串:

>>> [(str(len(list(c))), n) for n, c in groupby(s)] 
[('3', '1'), ('1', '3'), ('1', '1'), ('2', '2'), ('2', '1'), ('1', '0')] 

要獲得下一個數字,您需要join所有這些。要做到這一點,「鏈」他們:

>>> from itertools import chain 
>>> ''.join(chain(*[(str(len(list(c))), n) for n, c in groupby(s)])) 
'311311222110' 

當然,你可能想在最後一個整數,如果你不希望只是打印:

>>> int(''.join(chain(*[(str(len(list(c))), n) for n, c in groupby(s)]))) 
311311222110 

要獲得英語描述,我會使用一個字典來獲取英文單詞:

nwords = {'0': zero, '1': 'one', '2': 'two', '3': 'three'} # etc. 
for c, n in [(str(len(list(c))), n) for n, c in groupby(s)]: 
    print "{c} {n}{p}".format(p='' if c=='1' else 's', c=nwords[c], n=nwords[n]) 

它打印:

three ones 
one three 
one one 
two twos 
two ones 
one zero 

我會讓你把這些部分放在一起得到一些需要索引的東西,遞歸地計算以前的答案以給出最終答案。

3

首先,這些:

def strHead(s): 
    """strHead: String -> String""" 
    return s[0] 

def strTail(s, run): 
    """strTail: String -> String""" 
    return s[:] 

他們沒有做任何有用的;第一個返回項0,第二個返回字符串。查克他們。

然後

def runLenAux(s, c): 
    if s == "": 
     return 0 
    else: 
     if strHead(s)== c: 
      return 1 + int(runLenAux(strTail(s), c)) 
     else: 
      return 0 

現在有一個明顯的問題。當他們充其量是列表中的數字時,您會將這些數字視爲相同數字。但其他時候,你會像串線一樣對待它們。

讓我們把它們看成像列表一樣,因爲它更明顯。

所以:

def runLenAux(s, c): 

什麼是sc?不知道。我想這是爲了獲得下一個值,所以做一個[1, 0] → [1, 1, 1, 0]映射。所以讓我們拿一個列表:

def look_and_say(term): 
    """Looks at and says a term.""" 

而不是做你的搞笑->的東西,在Python 3,你可以註釋你的函數。通過向他們展示這個半掩蓋的事實來打動你的同齡人!

def look_and_say(term: "[int]") -> "[int]": 
    """Looks at and says a term.""" 

這裏我用"[int]"表示 「intlist的」。

那麼,下一個部分:

if s == "": 
     return 0 

天哪!你計劃使用遞歸嗎?這太多了!我們不是Haskell在這裏!

行,從頂部。我們想重複一遍,記下我們看過的同一件物品的數量,是的?因此,我們可以做一個循環,如:

for item in term: 
    count how many are the same 
    if different, break 

(。這聽起來象是一個已經做過好,它有它的所謂itertools.groupby讓我們假設你不知道的是,雖然)。

count = 0 
match = None 
for item in term: 
    # If this isn't the same we should stop counting 
    if match != item: 
     do_something_with_count_and_match 

     # Start again from this item 
     count = 1 
     match = item 

    # If this is the same we should continue counting 
    else: 
     count = count + 1 

這看起來不錯!

怎麼把do_something_with_count_and_match?好吧,讓我們保持一個清單,把事情和Chuck在那裏

# This is what we're building 
next_term = [] 

... 
for item in term: 
    ... 
    if match != item: 
     # Say "One One" or "Two Threes" or "Three Ones", etc. 
     next_term.append(count) 
     next_term.append(match) 

     # Start again from this item 
     count = 1 
     match = item 
    ... 

所以我們的結果,它運行?

def look_and_say(term: "[int]") -> "[int]": 
    """Looks at and says a term.""" 
    # This is what we're building 
    next_term = [] 

    count = 0 
    match = None 
    for item in term: 
     # If this isn't the same we should stop counting 
     if match != item: 
      # Say "One One" or "Two Threes" or "Three Ones", etc. 
      next_term.append(count) 
      next_term.append(match) 

      # Start again from this item 
      count = 1 
      match = item 

     # If this is the same we should continue counting 
     else: 
      count = count + 1 

look_and_say([0]) 
#>>> 

嗯...沒有輸出。

啊,我們忘記了returnnext_term

def look_and_say(term: "[int]") -> "[int]": 
    ... # All that stuff 

    return next_term 

look_and_say([0]) 
#>>> [0, None] 

嗯..嗯,這是沒有好。我們需要確保我們不計算None佔位match

def look_and_say(term: "[int]") -> "[int]": 
    ... 
    for item in term: 
     ... 
     if match != item: 
      if match is not None: 
       next_term.append(count) 
       next_term.append(match) 
      ... 
    ... 

而且我們還需要加上最後一節,即使它不會觸發else(循環停止):

def look_and_say(term: "[int]") -> "[int]": 
    ... 
    for item in term: 
     ... 

    if match != item: 
     if match is not None: 
      next_term.append(count) 
      next_term.append(match) 

    return next_term 

那就試試吧:

def look_and_say(term: "[int]") -> "[int]": 
    """Looks at and says a term.""" 
    # This is what we're building 
    next_term = [] 

    count = 0 
    match = None 
    for item in term: 
     # If this isn't the same we should stop counting 
     if match != item: 
      # Say "One One" or "Two Threes" or "Three Ones", etc. 
      if match is not None: 
       next_term.append(count) 
       next_term.append(match) 

      # Start again from this item 
      count = 1 
      match = item 

     # If this is the same we should continue counting 
     else: 
      count = count + 1 

    if match is not None: 
     next_term.append(count) 
     next_term.append(match) 

    return next_term 

look_and_say([0]) 
#>>> [1, 0] 

look_and_say([1, 0]) 
#>>> [1, 1, 1, 0] 

look_and_say([1, 1, 1, 0]) 
#>>> [3, 1, 1, 0] 

呀!

我這樣做是爲了向你展示編程不是魔術。你只需要繼續嘗試和應用你所知道的。

個人而言,我會實現它是這樣的:

from itertools import groupby 

# What we just implemented 
def look_and_say(string): 
    for k, v in groupby(string): 
     yield sum(1 for _ in v) 
     yield k 

list(look_and_say([0])) 
#>>> [1, 0] 

list(look_and_say([1, 0])) 
#>>> [1, 1, 1, 0] 

list(look_and_say([1, 1, 1, 0])) 
#>>> [3, 1, 1, 0] 

但是,這只是因爲我知道groupby

1

而itertools.groupby()很容易,有時它的樂趣破解的東西一起

def foo(seed = '0', nbr_of_indexes = 6): 
    """returns a formatted string matching pattern described by OP 
    """ 
    def groups(s, match = None, count = 0, result = ''): 
     """count consecutive matches 

     returns str 
     """ 
     # recursion base case, no more s 
     if not s: 
      result += (str(count) + match) 
      return result 
     # initialize match 
     if not match: 
      match = s[0] 
     if s[0] == match: 
      count += 1 
     else: 
      result += (str(count) + match) 
      match = s[0] 
      count = 1 
     return groups(s[1:], match, count, result) 
    result = [(0,'0')] 
    for index in xrange(1, nbr_of_indexes + 1): 
     result.append((index, groups(seed))) 
     seed = result[-1][1] 
    return ''.join(['{}\t{}\n'.format(*thing) for thing in result])  

>>> print foo() 
0 0 
1 10 
2 1110 
3 3110 
4 132110 
5 1113122110 
6 311311222110 

>>> 

編輯:改變組()進行分組和計數整個字符串,而不只是第一個項目

+0

有沒有辦法不使用追加功能? – user123456789101112

+0

追加是列表對象方法不是函數。代碼可以在沒有它的情況下重寫。 – wwii

+0

有沒有辦法讓它不使用列表? – user123456789101112