CodingTour
ARTS #3

Algorithm

本周选择的算法题是:Integer to English Words

规则如下:

Convert a non-negative integer to its english words representation. Given input is guaranteed to be less than \(2^{31}-1\).

Example 1:

Input: 123
Output: "One Hundred Twenty Three"

Example 2:

Input: 12345
Output: "Twelve Thousand Three Hundred Forty Five"

Example 3:

Input: 1234567
Output: "One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven"

Example 4:

Input: 1234567891
Output: "One Billion Two Hundred Thirty Four Million Five Hundred Sixty Seven Thousand Eight Hundred Ninety One"

Solution

我实现的方案:

Runtime:32 ms,快过 97.28%。

Memory:13.2 MB,低于 52.89%。

class Solution:

    num_map = {
        1: "One", 2: "Two", 3: "Three", 4: "Four", 5: "Five",
        6: "Six", 7: "Seven", 8: "Eight", 9: "Nine", 10: "Ten",
        11: "Eleven", 12: "Twelve", 13: "Thirteen", 14: "Fourteen",
        15: "Fifteen", 16: "Sixteen", 17: "Seventeen", 18: "Eighteen", 19: "Nineteen",
        20: "Twenty", 30: "Thirty", 40: "Forty", 50: "Fifty", 60: "Sixty",
        70: "Seventy", 80: "Eighty", 90: "Ninety",
    }

    carry_map = {
        100: "Hundred",
        1000: "Thousand",
        100000: "Hundred",
        1000000: "Million",
        100000000: "Hundred",
        1000000000: "Billion",
    }

    def numberToWords(self, num: int) -> str:
        if num == 0:
            return "Zero"

        result = None
        carry = 1

        while num > 0:
            num_bit = num % 1000

            if num_bit > 0:
                high = int(num_bit / 100)
                low_digits = num_bit % 100
                if low_digits < 20:
                    middle = low = 0
                else:
                    middle = int(num_bit / 10) % 10
                    low = num_bit % 10
                    low_digits = 0
                low_carry = Solution.carry_map.get(carry)

                for word in [
                    None if low_carry is None else low_carry,
                    None if low_digits == 0 else Solution.num_map.get(low_digits),
                    None if low == 0 else Solution.num_map.get(low),
                    None if middle == 0 else Solution.num_map.get(middle * 10),
                    None if high == 0 else Solution.num_map.get(high) + " " + Solution.carry_map.get(carry * 100),
                ]:
                    if word is not None:
                        result = word + ("" if result is None else (" " + result))

            num = int(num / 1000)
            carry *= 1000

        return result

我在内存中放置了两张表,一张对应数字,一张对应进位。

numberToWords里将数字每三位作为一个整体单独转换:

  1. 将 123456789 从低位开始分解成 789、456、123 三个区间
  2. 如果区间的三个数字为0,直接跳过,如 1000001 转换为 “One Million One”
  3. 区间不为0,将数字转换为对应的 words,补上单位
  4. Done

按三位分解,独自转换,然后拼接在一起,进位表需要将单位全部覆盖。

Review

Let’s Talk Architechture
我很喜欢作者的观点。全文总结了 iOS 过去这些年架构演化的过程:

  • The Past

    • MVC,不同于经典的 MVC,Apple 的 MVC 名声可不好,原本的 View 层是可直接与 Model 层通信,但是 Apple 将 Controller 层作为胶水粘合 View 和 Model,最终让 Controller 变成一个庞然大物,3层架构的 MVC 看起来像是2层架构
  • The Present
    • MVVM,这是在 iOS 开发者之间广为流传的第一个替代方案,它是一个3层架构,相比之下,它的每一层都很容易测试,你不再需要构建一个 View 去测试 ViewModel,触发一些行为并记录下结果就可以很轻松的完成测试。它也有缺点,View 与 ViewModel 的粒度不好把握,View 与 View 之间的动画不好联动
    • MVP,Apple 的架构图虽然是 MVC,但更像是 MVP,这也是一种在 iOS 之外很流行的架构,很老,比 MVVM 更老,但是它也是一个3层架构,只要理解了 Controller 或 Presenter 不必须是 ViewController 就能让架构变得更清晰、易维护。事实上我使用 MVP 已经很多年了,大概从14、15年开始,做了很多基于 MVP 的设计,引入了双向数据绑定等,目前来说都还是很好用的方案
  • The Future
    • Elm,作者展望未来,认为像 React、Vue 这种具有 Diff 算法局部更新 UI 的方式可能会成为未来的方向。Elm 包含三个基本的部分:

      • Model,程序状态
      • Update,更新状态
      • View,展示状态

      这是一个标准的3层架构,其实所有的架构无非就是三种角色:

      • 数据管理者
      • 数据加工者
      • 数据展示者

      UI 绑定是现在架构处理的难点,拭目以待吧。

Tip

本周学习到的一些内容:

  • JS 动态属性名:
    const dynamic = 'email';
    let user = {
      name: 'John',
      [dynamic]: 'john@doe.com'
    }
    console.log(user); // outputs { name: "John", email: "john@doe.com" }
    
  • 响应式函数编程
    • 简单却强大
    • 申明式的步骤让代码更容易理解
    • 让复杂的流程变得容易管理和表示
    • 冷信号,还没有开始传递事件,每一个新的订阅都会开启一个信号
    • 热信号,已经开始传递事件,新的订阅者不会开启一个信号

Share

本周分享 ReactiveCocoa vs RxSwift,虽然是一篇老文,语法层面可能已经过时,但是观点依然值得一看。

大家都喜欢 Nike,但是为什么还有人穿着 Adidas :)
Why are developers still using Angular?,这篇文章让我开始反思 Angular 有哪些优势是 React 所不具备的,以往谈起 Angular 时总是会想起它陡峭的学习曲线以及老用户不如狗的更新策略,框架都有自己擅长的一面,不如放下比较,从一次创作开始感受它们各自的美妙。