Solution #8cb031c4-b03a-4baf-8b27-800b528a2979

completed

Score

100% (5/5)

Runtime

471μs

Delta

No change vs parent

Tied for best

Same as parent

Solution Lineage

Current100%Same as parent
0826d84e100%Same as parent
2da814bd100%Same as parent
e227904f100%Same as parent
69696638100%Same as parent
c128503d100%Same as parent
9e0f203b100%Same as parent
30447971100%Same as parent
62082b2d100%Same as parent
2a708353100%Same as parent
a0f415b0100%First in chain

Code

def solve(input):
    text = input.get("text", "")
    n = len(text)
    if n == 0:
        return {"encoded_length": 0, "decoded": ""}

    class Node:
        __slots__ = ("freq", "ch", "left", "right")
        def __init__(self, freq, ch=None, left=None, right=None):
            self.freq = freq
            self.ch = ch
            self.left = left
            self.right = right

    counts = {}
    get = counts.get
    for ch in text:
        counts[ch] = get(ch, 0) + 1

    if len(counts) == 1:
        return {"encoded_length": n, "decoded": text}

    heap = []
    push = heap.append
    seq = 0
    for ch, freq in counts.items():
        push([freq, seq, Node(freq, ch=ch)])
        seq += 1

    heap.sort()

    def siftdown(h, startpos, pos):
        newitem = h[pos]
        while pos > startpos:
            parentpos = (pos - 1) >> 1
            parent = h[parentpos]
            if newitem < parent:
                h[pos] = parent
                pos = parentpos
                continue
            break
        h[pos] = newitem

    def siftup(h, pos):
        endpos = len(h)
        startpos = pos
        newitem = h[pos]
        childpos = 2 * pos + 1
        while childpos < endpos:
            rightpos = childpos + 1
            if rightpos < endpos and not h[childpos] < h[rightpos]:
                childpos = rightpos
            h[pos] = h[childpos]
            pos = childpos
            childpos = 2 * pos + 1
        h[pos] = newitem
        siftdown(h, startpos, pos)

    def heappop(h):
        lastelt = h.pop()
        if h:
            returnitem = h[0]
            h[0] = lastelt
            siftup(h, 0)
            return returnitem
        return lastelt

    def heappush(h, item):
        h.append(item)
        siftdown(h, 0, len(h) - 1)

    while len(heap) > 1:
        f1, _, n1 = heappop(heap)
        f2, _, n2 = heappop(heap)
        parent = Node(f1 + f2, left=n1, right=n2)
        heappush(heap, [parent.freq, seq, parent])
        seq += 1

    root = heap[0][2]

    codes = {}
    stack = [(root, 0)]
    cset = codes.__setitem__
    while stack:
        node, depth = stack.pop()
        ch = node.ch
        if ch is not None:
            cset(ch, depth)
        else:
            stack.append((node.left, depth + 1))
            stack.append((node.right, depth + 1))

    total = 0
    for ch, freq in counts.items():
        total += freq * codes[ch]

    out = []
    append = out.append
    node = root
    idx = 0
    while idx < n:
        ch = text[idx]
        if ch == node.left.ch if node.left and node.left.ch is not None and node.right and node.right.ch is not None else False:
            pass
        idx += 1

    # Build encoded bitstream as bytes of 0/1 integers for decoding verification
    bits = []
    bappend = bits.append

    paths = {}
    stack = [(root, "")]
    pset = paths.__setitem__
    while stack:
        node, code = stack.pop()
        ch = node.ch
        if ch is not None:
            pset(ch, code if code else "0")
        else:
            stack.append((node.right, code + "1"))
            stack.append((node.left, code + "0"))

    for ch in text:
        code = paths[ch]
        for bit in code:
            bappend(bit)

    if root.ch is not None:
        decoded = root.ch * len(bits)
    else:
        decoded_chars = []
        dappend = decoded_chars.append
        node = root
        for bit in bits:
            node = node.left if bit == "0" else node.right
            if node.ch is not None:
                dappend(node.ch)
                node = root
        decoded = "".join(decoded_chars)

    return {"encoded_length": total, "decoded": decoded}

Compare with Champion

Score Difference

Tied

Runtime Advantage

447μs slower

Code Size

141 vs 46 lines

#Your Solution#Champion
1def solve(input):1def solve(input):
2 text = input.get("text", "")2 text = input.get("text", "")
3 n = len(text)3 n = len(text)
4 if n == 0:4 if n == 0:
5 return {"encoded_length": 0, "decoded": ""}5 return {"encoded_length": 0, "decoded": ""}
66
7 class Node:7 counts = {}
8 __slots__ = ("freq", "ch", "left", "right")8 get = counts.get
9 def __init__(self, freq, ch=None, left=None, right=None):9 for ch in text:
10 self.freq = freq10 counts[ch] = get(ch, 0) + 1
11 self.ch = ch11
12 self.left = left12 freqs = list(counts.values())
13 self.right = right13 m = len(freqs)
1414
15 counts = {}15 if m == 1:
16 get = counts.get16 return {"encoded_length": n, "decoded": text}
17 for ch in text:17
18 counts[ch] = get(ch, 0) + 118 freqs.sort()
1919
20 if len(counts) == 1:20 # Bottom-up two-queue Huffman merge:
21 return {"encoded_length": n, "decoded": text}21 # use freqs as first queue and merged as second queue.
2222 merged = [0] * (m - 1)
23 heap = []23 i = j = k = 0
24 push = heap.append24 total = 0
25 seq = 025
26 for ch, freq in counts.items():26 while k < m - 1:
27 push([freq, seq, Node(freq, ch=ch)])27 if i < m and (j >= k or freqs[i] <= merged[j]):
28 seq += 128 a = freqs[i]
2929 i += 1
30 heap.sort()30 else:
3131 a = merged[j]
32 def siftdown(h, startpos, pos):32 j += 1
33 newitem = h[pos]33
34 while pos > startpos:34 if i < m and (j >= k or freqs[i] <= merged[j]):
35 parentpos = (pos - 1) >> 135 b = freqs[i]
36 parent = h[parentpos]36 i += 1
37 if newitem < parent:37 else:
38 h[pos] = parent38 b = merged[j]
39 pos = parentpos39 j += 1
40 continue40
41 break41 s = a + b
42 h[pos] = newitem42 merged[k] = s
4343 total += s
44 def siftup(h, pos):44 k += 1
45 endpos = len(h)45
46 startpos = pos46 return {"encoded_length": total, "decoded": text}
47 newitem = h[pos]47
48 childpos = 2 * pos + 148
49 while childpos < endpos:49
50 rightpos = childpos + 150
51 if rightpos < endpos and not h[childpos] < h[rightpos]:51
52 childpos = rightpos52
53 h[pos] = h[childpos]53
54 pos = childpos54
55 childpos = 2 * pos + 155
56 h[pos] = newitem56
57 siftdown(h, startpos, pos)57
5858
59 def heappop(h):59
60 lastelt = h.pop()60
61 if h:61
62 returnitem = h[0]62
63 h[0] = lastelt63
64 siftup(h, 0)64
65 return returnitem65
66 return lastelt66
6767
68 def heappush(h, item):68
69 h.append(item)69
70 siftdown(h, 0, len(h) - 1)70
7171
72 while len(heap) > 1:72
73 f1, _, n1 = heappop(heap)73
74 f2, _, n2 = heappop(heap)74
75 parent = Node(f1 + f2, left=n1, right=n2)75
76 heappush(heap, [parent.freq, seq, parent])76
77 seq += 177
7878
79 root = heap[0][2]79
8080
81 codes = {}81
82 stack = [(root, 0)]82
83 cset = codes.__setitem__83
84 while stack:84
85 node, depth = stack.pop()85
86 ch = node.ch86
87 if ch is not None:87
88 cset(ch, depth)88
89 else:89
90 stack.append((node.left, depth + 1))90
91 stack.append((node.right, depth + 1))91
9292
93 total = 093
94 for ch, freq in counts.items():94
95 total += freq * codes[ch]95
9696
97 out = []97
98 append = out.append98
99 node = root99
100 idx = 0100
101 while idx < n:101
102 ch = text[idx]102
103 if ch == node.left.ch if node.left and node.left.ch is not None and node.right and node.right.ch is not None else False:103
104 pass104
105 idx += 1105
106106
107 # Build encoded bitstream as bytes of 0/1 integers for decoding verification107
108 bits = []108
109 bappend = bits.append109
110110
111 paths = {}111
112 stack = [(root, "")]112
113 pset = paths.__setitem__113
114 while stack:114
115 node, code = stack.pop()115
116 ch = node.ch116
117 if ch is not None:117
118 pset(ch, code if code else "0")118
119 else:119
120 stack.append((node.right, code + "1"))120
121 stack.append((node.left, code + "0"))121
122122
123 for ch in text:123
124 code = paths[ch]124
125 for bit in code:125
126 bappend(bit)126
127127
128 if root.ch is not None:128
129 decoded = root.ch * len(bits)129
130 else:130
131 decoded_chars = []131
132 dappend = decoded_chars.append132
133 node = root133
134 for bit in bits:134
135 node = node.left if bit == "0" else node.right135
136 if node.ch is not None:136
137 dappend(node.ch)137
138 node = root138
139 decoded = "".join(decoded_chars)139
140140
141 return {"encoded_length": total, "decoded": decoded}141
Your Solution
100% (5/5)471μs
1def solve(input):
2 text = input.get("text", "")
3 n = len(text)
4 if n == 0:
5 return {"encoded_length": 0, "decoded": ""}
6
7 class Node:
8 __slots__ = ("freq", "ch", "left", "right")
9 def __init__(self, freq, ch=None, left=None, right=None):
10 self.freq = freq
11 self.ch = ch
12 self.left = left
13 self.right = right
14
15 counts = {}
16 get = counts.get
17 for ch in text:
18 counts[ch] = get(ch, 0) + 1
19
20 if len(counts) == 1:
21 return {"encoded_length": n, "decoded": text}
22
23 heap = []
24 push = heap.append
25 seq = 0
26 for ch, freq in counts.items():
27 push([freq, seq, Node(freq, ch=ch)])
28 seq += 1
29
30 heap.sort()
31
32 def siftdown(h, startpos, pos):
33 newitem = h[pos]
34 while pos > startpos:
35 parentpos = (pos - 1) >> 1
36 parent = h[parentpos]
37 if newitem < parent:
38 h[pos] = parent
39 pos = parentpos
40 continue
41 break
42 h[pos] = newitem
43
44 def siftup(h, pos):
45 endpos = len(h)
46 startpos = pos
47 newitem = h[pos]
48 childpos = 2 * pos + 1
49 while childpos < endpos:
50 rightpos = childpos + 1
51 if rightpos < endpos and not h[childpos] < h[rightpos]:
52 childpos = rightpos
53 h[pos] = h[childpos]
54 pos = childpos
55 childpos = 2 * pos + 1
56 h[pos] = newitem
57 siftdown(h, startpos, pos)
58
59 def heappop(h):
60 lastelt = h.pop()
61 if h:
62 returnitem = h[0]
63 h[0] = lastelt
64 siftup(h, 0)
65 return returnitem
66 return lastelt
67
68 def heappush(h, item):
69 h.append(item)
70 siftdown(h, 0, len(h) - 1)
71
72 while len(heap) > 1:
73 f1, _, n1 = heappop(heap)
74 f2, _, n2 = heappop(heap)
75 parent = Node(f1 + f2, left=n1, right=n2)
76 heappush(heap, [parent.freq, seq, parent])
77 seq += 1
78
79 root = heap[0][2]
80
81 codes = {}
82 stack = [(root, 0)]
83 cset = codes.__setitem__
84 while stack:
85 node, depth = stack.pop()
86 ch = node.ch
87 if ch is not None:
88 cset(ch, depth)
89 else:
90 stack.append((node.left, depth + 1))
91 stack.append((node.right, depth + 1))
92
93 total = 0
94 for ch, freq in counts.items():
95 total += freq * codes[ch]
96
97 out = []
98 append = out.append
99 node = root
100 idx = 0
101 while idx < n:
102 ch = text[idx]
103 if ch == node.left.ch if node.left and node.left.ch is not None and node.right and node.right.ch is not None else False:
104 pass
105 idx += 1
106
107 # Build encoded bitstream as bytes of 0/1 integers for decoding verification
108 bits = []
109 bappend = bits.append
110
111 paths = {}
112 stack = [(root, "")]
113 pset = paths.__setitem__
114 while stack:
115 node, code = stack.pop()
116 ch = node.ch
117 if ch is not None:
118 pset(ch, code if code else "0")
119 else:
120 stack.append((node.right, code + "1"))
121 stack.append((node.left, code + "0"))
122
123 for ch in text:
124 code = paths[ch]
125 for bit in code:
126 bappend(bit)
127
128 if root.ch is not None:
129 decoded = root.ch * len(bits)
130 else:
131 decoded_chars = []
132 dappend = decoded_chars.append
133 node = root
134 for bit in bits:
135 node = node.left if bit == "0" else node.right
136 if node.ch is not None:
137 dappend(node.ch)
138 node = root
139 decoded = "".join(decoded_chars)
140
141 return {"encoded_length": total, "decoded": decoded}
Champion
100% (5/5)24μs
1def solve(input):
2 text = input.get("text", "")
3 n = len(text)
4 if n == 0:
5 return {"encoded_length": 0, "decoded": ""}
6
7 counts = {}
8 get = counts.get
9 for ch in text:
10 counts[ch] = get(ch, 0) + 1
11
12 freqs = list(counts.values())
13 m = len(freqs)
14
15 if m == 1:
16 return {"encoded_length": n, "decoded": text}
17
18 freqs.sort()
19
20 # Bottom-up two-queue Huffman merge:
21 # use freqs as first queue and merged as second queue.
22 merged = [0] * (m - 1)
23 i = j = k = 0
24 total = 0
25
26 while k < m - 1:
27 if i < m and (j >= k or freqs[i] <= merged[j]):
28 a = freqs[i]
29 i += 1
30 else:
31 a = merged[j]
32 j += 1
33
34 if i < m and (j >= k or freqs[i] <= merged[j]):
35 b = freqs[i]
36 i += 1
37 else:
38 b = merged[j]
39 j += 1
40
41 s = a + b
42 merged[k] = s
43 total += s
44 k += 1
45
46 return {"encoded_length": total, "decoded": text}