こんなのを見つけたので、腕試しにトライしてみたぜ。うん、8時間くらいかかったよね…。

なるたけ標準関数を使わないという縛りで挑戦してみた。いやほら、言語はなんでも良いみたいなので、できるだけ言語特有の機能は使わないほうがいいかなと思って。

# ==============================
# 問題1
# forループ、whileループ、および再帰を使用して、
# リスト内の数字の合計を計算する3つの関数を記述せよ。
# ==============================
lis = [0, 1, 2, 3, -4]

### for ###
result4for = 0
for l in lis:
    result4for += l
print("問題1(for):", result4for)

### while ###
result4while = 0
i = 0
while i < len(lis):
    result4while += lis[i]
    i += 1
print("問題1(while):", result4while)

### 再帰 ###
def func4saiki(res=0):
    if len(lis) == 0:
        return res
    else:
        res += lis[0]
        lis.pop(0)
        res = func4saiki(res)
        return res
print("問題1(再帰):", func4saiki())
# 実行結果
問題1(for): 2
問題1(while): 2
問題1(再帰): 2

再帰の、引数デフォルト値を使ってるところが若干縛りに触れるか…? デフォルト値って実質、while文のように処理外で変数を定義してるようなものだしさ? まあともかく問題1はとてもイージー。

# ==============================
# 問題2
# 交互に要素を取ることで、2つのリストを結合する関数を記述せよ。
# 例えば [a, b, c]と[1, 2, 3]という2つのリストを与えると、
# 関数は [a, 1, b, 2, c, 3]を返す。
# ==============================
lisA = ["a", "b", "c"]
lisB = [0, 1, 2, 3, 4]

def func4Q2():
    result = []
    maxlen = len(lisA) if len(lisA) >= len(lisB) else len(lisB)
    for i in range(maxlen):
        if i < len(lisA):
            result.append(lisA[i])
        if i < len(lisB):
            result.append(lisB[i])
    return result
print("問題2:", func4Q2())
# 実行結果
問題2: ['a', 0, 'b', 1, 'c', 2, 3, 4]

長さの異なるリストでも大丈夫なように書いたぜ。問題2もとってもイージー。

# ==============================
# 問題3
# 最初の100個のフィボナッチ数のリストを計算する関数を記述せよ。
# 定義では、フィボナッチ数列の最初の2つの数字は0と1で、次の数は前の2つの合計となる。
# 例えば最初の10個のフィボナッチ数列は、0, 1, 1, 2, 3, 5, 8, 13, 21, 34となる。
# ==============================
def func4Q3():
    result = [0, 1]
    while len(result) < 100:
        result.append(result[-1] + result[-2])
    return result
print("問題3:", func4Q3())
# 実行結果
問題3: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 長いので以下略

ふぃ、ふぃぼなっち? と一瞬破裂しかけたが、面食らうほどラクだった。一番簡単な問題。

# ==============================
# 問題4
# 正の整数のリストを与えられたとき、数を並び替えて可能な最大数を返す関数を記述せよ。
# 例えば、[50, 2, 1, 9]が与えられた時、95021が答えとなる。
# ==============================
lis4Q4 = [100, 50, 2, 1, 99, 98, 3, 3, 9, 10]

def bossSort(lis):
    if len(lis) <= 1:
        return lis
    else:
        base     = lis[0]
        len_base = len(str(base))
        biggerList  = []
        smallerList = []
        equalList   = []
        for num in lis:
            len_num = len(str(num))
            # baseとnumの桁差を9で揃える 5と555なら、599と555にする
            digit = len_base if len_base >= len_num else len_num
            b = int(str(base).ljust(digit, "9"))
            n = int(str(num).ljust(digit, "9"))
            # 揃えた数値で比較するが、biggerListとかに追加するのは揃える前の数値
            if   n > b: biggerList.append(num)
            elif n < b: smallerList.append(num)
            else      : equalList.append(num)
        biggerList  = bossSort(biggerList)
        smallerList = bossSort(smallerList)
        return biggerList + equalList + smallerList

def func4Q4_2():
    sortedList = bossSort(lis4Q4)
    result = ""
    for num in sortedList:
        result += str(num)
    return result

print("問題4:", func4Q4_2())
# 実行結果
問題4: 9999850332110100

突然難度の跳ね上がった問題4。これは数値を文字列として扱い、より「一文字目が9に近い」「一文字に近い」ものを優先してソートする問題だろうと思う。俺はまず一文字目が大きい順にリストの要素を取り出し、次に、たとえば「5」と「55」の比較であれば「5」のほうを「59」に変換して数値比較することで実現した。縛りの関係上ソート処理を自分で書いたんだけど、そこに時間がかかったなー。

# ==============================
# 問題5
# 1,2,…,9の数をこの順序で、"+"、"-"、
# またはななにもせず結果が100となるあらゆる組合せを出力するプログラムを記述せよ。
# 例えば、1 + 2 + 34 – 5 + 67 – 8 + 9 = 100となる。
# ==============================
print("===== 問題5 =====")
for i in range(3**8):
    numList = [1]
    for j in range(2, 10):
        if   i % 3 == 0:
            numList.append(j)
        elif i % 3 == 1:
            numList.append(-j)
        elif i % 3 == 2:
            lastNum = numList[-1]
            numList[-1] = lastNum * 10 + (j if (lastNum > 0) else -j)
        i //= 3

    # print処理
    if sum(numList) == 100:
        result = ""
        for num in numList:
            result += ("+"+str(num)) if (num > 0 and num != numList[0]) else str(num)
        print(result)
# 実行結果
===== 問題5 =====
1+23-4+56+7+8+9
12+3-4+5+67+8+9
1+2+34-5+67-8+9
1+2+3-4+5+6+78+9
123-4-5-6-7+8-9
123+45-67+8-9
1+23-4+5+6+78-9
12-3-4+5-6+7+89
12+3+4+5-6-7+89
123-45-67+89
123+4-5+67-89

1から9のそれぞれの数字の間に +, -, (空白) を挟む問題。パターンは全部で3**8=6561通りになるはずだから、ループを6561周まわすのは確定。このループ数(0から6560)を3進数として扱うと 00000000 から 22222222 になるので、この一桁一桁を +, -, (空白) に対応させることで3**8パターンを実現することにする。どういうことかっていうと、たとえばループ番号(i)が5のとき3進数では 00000012 となるが、これを + + + + + + - (空白) として扱い、 [1, +2, +3, +4, +5, +6, +7, -89] というパターンを作り出すってことだ。3進数におけるそれぞれの桁にアクセスするには一桁目の取得と桁上りが必要だが、それぞれ「その数を3で割ったときの余り」「その数を3で割る」ことで可能。 いやまあ、

patterns = ["+", "-", ""]
for a in patterns:
    for b in patterns:
        for c in patterns:
            for d in patterns:
                for e in patterns:
                    for f in patterns:
                        for g in patterns:
                            for h in patterns:
                                if eval("1%s2%s3%s4%s5%s6%s7%s8%s9" % (a,b,c,d,e,f,g,h)) == 100:
                                    print("1%s2%s3%s4%s5%s6%s7%s8%s9" % (a,b,c,d,e,f,g,h))

ぶっちゃけコレでいいんだけどね? こっちは完全に力技だがシンプルで、美しさすらある。しかし標準関数のeval()を使っちゃってるから、縛りの都合上他の方法を考えた結果が上の3進数方式だ。