# 6141-二进制转十进制

# 题目描述

Implement BinaryToDecimal<S> which takes an exact string type S consisting 0 and 1 and returns an exact number type corresponding with S when S is regarded as a binary. You can assume that the length of S is equal to or less than 8 and S is not empty.

type Res1 = BinaryToDecimal<'10'>; // expected to be 2
type Res2 = BinaryToDecimal<'0011'>; // expected to be 3

# 分析

想要实现二进制转十进制,只需要不断相加,比如 0011 = 1 * 1 + 1 * 2 + 0 * 4 + 0 * 8 = 3

可以从后往前遍历,然后设置一个辅助元组,每次往前遍历一个元素,就把辅助元组进行翻倍。从而产出

1 -> 2 -> 4 -> 8 -> 16

如果当前元素为 1,那么就把辅助元组的值增加到结果中(所以也需要一个结果元组),否则不增加。

比如:0(不加) -> 1(加2) -> 0(不加) -> 1(加8) -> 0(不加),得到 10。

依次类推,当遍历结束时,结果的元组的长度就是答案。

# 题解

// 字符转元组,因为字符不好匹配最后一个元素
// 元组可以通过扩展操作符控制匹配
type StringToUnion<T extends string> = T extends `${infer F}${infer R}`
  ? [F, ...StringToUnion<R>]
  : [];

type Add<T extends any[], Res extends any[] = [], Acc extends any[] = [1]> =
  // 匹配最后一个元素
  T extends [...infer R, infer L]
    ? // 如果最后一个元素是 1
      L extends '1'
      ? // 那么把 Acc 加到 Res 中,并对 Acc 进行翻倍
        // Acc 的变化:1 -> 2 -> 4 -> 8 -> 16
        Add<R, [...Res, ...Acc], [...Acc, ...Acc]>
      : // 否则,Res不变,并对 Acc 进行翻倍
        Add<R, Res, [...Acc, ...Acc]>
    : // 遍历完毕,返回 res 的长度就是结果
      Res['length'];

type BinaryToDecimal<S extends string> = Add<StringToUnion<S>>;

# 知识点

  1. 辅助元组计数
  2. 元组遍历更加灵活,本题从后往前更容易理解
Last Updated: 2023/5/16 06:00:28