CodingTour
ARTS #208 | 深圳爱你

“来了就是深圳人” 的口号响彻大江南北,成为了深圳开放包容的生动体现~

Algorithm

本周选择的算法题是:Painting the Walls

impl Solution {
    pub fn paint_walls(cost: Vec<i32>, time: Vec<i32>) -> i32 {
        let mut dp = vec![vec![-1; cost.len() * 2 + 1]; cost.len() + 1];
        Self::dfs(0, cost.len(), &cost, &time, &mut dp)
    }

    fn dfs(i: usize, skip: usize, cost: &[i32], time: &[i32], dp: &mut [Vec<i32>]) -> i32 {
        if cost.len() * 2 - i <= skip {
            return 0;
        }

        if i == cost.len() {
            return 1_000_000_000;
        }

        if dp[i][skip] == -1 {
            dp[i][skip] = Self::dfs(i + 1, skip - 1, cost, time, dp).min(
                cost[i] + Self::dfs(i + 1, skip + time[i] as usize, cost, time, dp)
            );
        }
        dp[i][skip]
    }
}

Review

https://blog.jetbrains.com/kotlin/2023/11/kotlin-multiplatform-stable/

从 KMM 推出第一个 Beta 版至今已一年有余,支持所有的主流平台:

  • JVM
  • JS
  • Android / Android NDK
  • Apple
  • Linux
  • Windows
  • WebAssembly

KMM 不追求绝对的统一,它的架构看起来是这样的:

以生成 UUID 为例,它的代码实际等价为:

// Common
expect fun randomUUID(): String

// Android
import java.util.*
actual fun randomUUID() = UUID.randomUUID().toString()

// iOS
import platform.Foundation.NSUUID
actual fun randomUUID(): String = NSUUID().UUIDString()

尽管如此,KMM 在非 UI 场景下的代码复用率最高达到了 63%:

当前 KMM 的问题主要还是在生态建设上,你可以从 Awesome Kotlin Multiplatform 上找到对 KMM 友好的三方库,能选择的不多,好在大多处于活跃状态。

Tip

著名的 Mach-O 格式分析工具 MachOView 更新了 3.0 版本,这是时隔 8 年的更新,作者宣称提高了解析的健壮性,并提供了一个通用的二进制文件以同时支持 x86_64 和 arm64 架构。

Share

早前为了在 DevOps 流程中拿到 Xcode 在构建过程中的日志,使用了如下方法:

process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while process.poll() is None:
  	output = process.stdout.readline() or process.stderr.readline()
    ...

不过这种方法在最新版本的 macOS 14 和 Xcode 15 中失效了,如果这么写会导致阻塞,表现为构建过程停留在 GatherProvisioningInputs 处。

猜测是由于多个进程 or 线程互相等待对方释放资源引起的,所以设置文件描述符的阻塞模式可以解决该问题:

xcode_version = subprocess.check_output("xcodebuild -version", shell=True).decode("utf-8")
if "Xcode 15." in xcode_version: # 在构建机器上针对 Xcode 15 的兼容,低于 Xcode 15 的版本使用的是 macOS 13
    os.set_blocking(process.stdout.fileno(), False)
    os.set_blocking(process.stderr.fileno(), False)

但这种方式对性能影响很大,就像自旋锁一样是在让 CPU 空转,更好的处理方法是将 stderr 重定向到 stdout 中:

process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while process.poll() is None:
  	output = process.stdout.readline()
    ...

也能避免问题发生。