【问题标题】:LeetCode 1: How to translate the question two sum from ReasonML to Clojure? [closed]LeetCode 1:如何将问题二和从 ReasonML 转换为 Clojure? [关闭]
【发布时间】:2020-09-28 04:23:45
【问题描述】:

我在 ReasonML/Ocaml 中做了“TwoSum”的问题,但我不知道如何在 Clojure 中使用类似的伪算法进行编码。请评论如何将此解决方案翻译成 Clojure

Clojure

(def nums [2 7 11 15])
(def target 9)

(defn two-sum [n xs]
  (let [ixs (map vector xs (range (count xs)))]))

ReasonML

  module TwoSum: {
    let twoSum: (int, Belt.List.t(int)) => list(list(int));
    let run: unit => unit;
  } = {

    let logl = l => l |> Array.of_list |> Js.log;

    let concatmap = (xs: list('a), f) => {
      List.concat(List.map(x => f(x), xs));
    };

    let twoSum = (n, xs) => {
      let ixs = Belt.List.zip([0, ...range(1, List.length(xs))], xs);
      concatmap(ixs, ((i, x)) =>
        concatmap(drop(i, ixs), ((j, y)) => x + y == n ? [[i, j]] : [])
      );
    };

    let run = () => {
      Printf.printf("1. Two Sum :\n");
      let res = twoSum(21, [0, 2, 11, 19, 90, 10]);
      res |> logl;

    };
  };

【问题讨论】:

标签: algorithm clojure functional-programming reason


【解决方案1】:

您可以使用for 列出所有可能的索引对,并使用:when 选项过滤满足二和条件的对。这将返回一系列可能的解决方案。然后你选择第一个解决方案。

(defn two-sum [numbers target]
  (let [inds (range (count numbers))]
    (first (for [i inds
                 j inds
                 :when (and (not= i j)
                            (= target (+ (nth numbers i)
                                         (nth numbers j)))) ]
             [i j]))))

(two-sum [2 7 11 15] 9)
;; => [0 1]

【讨论】:

    【解决方案2】:

    我会选择更实用的风格:

    从创建pairs函数开始:

    (defn pairs [data]
      (->> data
           (iterate rest)
           (take-while seq)
           (mapcat (fn [[x & xs]] (map (partial vector x) xs)))))
    
    user> (pairs [:a :b :c :d])
    ;;=> ([:a :b] [:a :c] [:a :d] [:b :c] [:b :d] [:c :d])
    

    然后您可以生成那些索引到项目元组对:

    user> (pairs (map-indexed vector [:a :b :c]))
    ;;=> ([[0 :a] [1 :b]] 
    ;;    [[0 :a] [2 :c]] 
    ;;    [[1 :b] [2 :c]])
    

    所以你只需要保留你需要的对:

    (defn sum2 [target data]
      (->> data
           (map-indexed vector)
           pairs
           (keep (fn [[[i x] [j y]]]
                   (when (== target (+ x y))
                     [i j])))))
    
    user> (sum2 9 [2 7 11 15])
    ;;=> ([0 1])
    

    另一种选择是为此使用列表推导:

    (defn sum2 [target data]
      (for [[[i x] & xs] (->> data
                              (map-indexed vector)
                              (iterate rest)
                              (take-while seq))
            [j y] xs
            :when (== target (+ x y))]
        [i j]))
    
    user> (sum2 9 [2 7 11 15])
    ;;=> ([0 1])
    

    【讨论】:

      【解决方案3】:

      作为一个细微的变化,我会使用辅助函数 indexed[:a :b :c] 转换为:

      [[0 :a]
       [1 :b]
       [2 :c]]
      

      然后我们得到:

      (defn indexed
        [vals]
        (mapv vector (range) vals))
      
      (defn two-sum
        [vals tgt]
        (let [idx-vals (indexed vals)]
          (first
            (for [[i x] idx-vals  ; destructure each pair => local vars i & x
                  [j y] idx-vals
                  :when (and (< i j)
                          (= tgt (+ x y)))]
              [i j]))))
      

      结果

      (two-sum [2 7 11 15] 666)     => nil
      (two-sum [2 7 11 15] 9)       => [0 1]
      (two-sum [0 1 2 7 11 15] 9)   => [2 3]
      

      【讨论】:

        猜你喜欢
        • 2022-06-12
        • 2013-11-13
        • 2016-09-14
        • 2020-05-01
        • 2020-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-16
        相关资源
        最近更新 更多