2021年02月03日 : RustでLeetCode

先日も書いた通り

LeetCodeをやっていて、なるべくRustでコードを書くようにしてるのですが、 とにもかくにも、面倒なんですよね……。 たとえば、二分木の問題なんかは、Pythonだと

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

なんてわかりやすい定義なんですが、Rustだと

#[derive(Debug, PartialEq, Eq)]
pub struct TreeNode {
  pub val: i32,
  pub left: Option<Rc<RefCell<TreeNode>>>,
  pub right: Option<Rc<RefCell<TreeNode>>>,
}

impl TreeNode {
  #[inline]
  pub fn new(val: i32) -> Self {
    TreeNode {
      val,
      left: None,
      right: None
    }
  }
}

こうなります。 構造体のようでいて、Option/Rc/RefCellの理解が必須という鬼のような状況です。

Listはもうちょっと簡単なんですが、

#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
  pub val: i32,
  pub next: Option<Box<ListNode>>
}

impl ListNode {
  #[inline]
  fn new(val: i32) -> Self {
    ListNode {
      next: None,
      val
    }
  }
}

まぁ、当然のようにOption/Boxの組み合わせとなります。 LeetCodeだとテストとかしたいわけですが、やろうとするとノードが1個しかないような木でも 以下みたいな事になります。

#[test]
fn test_case1() {
assert_eq!(
    Solution::is_valid_bst(Some(Rc::new(RefCell::new(TreeNode::new(1))))),
        true
    );
}

ツライ……。

ということで、上記を

#[test]
fn test_case1() {
assert_eq!(
    Solution::is_valid_bst(TreeNode::from_str("[1]")),
        true
    );
}

のように書けるようにするべく頑張ってみようかと ちょっと頑張りだしました 。 調べたら、誰かもう作ってるだろうけど、まぁこれも鍛錬です。

で、ひとまず、コードはとても効率的ではなさそうなのですが、上記のようなテストが書けるようになった……と思ったんですが、 おもいっきりclippyに怒られて泣いています 。 clippyっていうのは、Rustのlintなんですね……。 怒られてるのはごもっともなのでなんとかしたいのですが、ジェネリクス使ったparse()のエラー処理で困っています。 誰かオシエテ。 どうせleetcodeではノードにはi32しかこなさそうなので、i32で作ってしまえばよかったかしら……。

ちなみに、これを作っていたため、昨日は dailyの問題(Treeの問題) を しっかり解きそびれました!! うぉーー。