5

docjureを使用していますが、select-columns関数の列マップが必要です。手動で指定せずに、すべての列を取得したいと思います。怠惰な無限ベクトルシーケンスとして以下を生成するにはどうすればよいですか[:A:B:C:D:E ...:AA:AB:AC ....:ZZ ...:XFD]?

4

7 に答える 7

6

あなたの質問は要約すると、「数字をアルファベットAZの26を底とする文字列に変換するにはどうすればよいですか?」です。

これを行う1つの方法があります-おそらく最も簡潔な方法ではありませんが、それをよりエレガントにすることは読者のための練習として残されています:)。

0〜25の数字は「A」〜「Z」にマップされ、26の数字は「AA」などにマップされると想定します。まずto-col、整数を列キーワードに変換する関数を定義します。その関数を使用して、無限のシーケンスを生成できます。

(defn to-col [num]
  (loop [n num s ()]
    (if (> n 25)
      (let [r (mod n 26)]
        (recur (dec (/ (- n r) 26)) (cons (char (+ 65 r)) s)))
      (keyword (apply str (cons (char (+ 65 n)) s))))))

これにより、列キーワードの無限のシーケンスを生成する方法が得られます。

(take 100 (map to-col (range)))
;; => (:A :B :C :D :E :F :G :H :I :J :K :L :M :N :O :P :Q :R :S :T :U :V :W
;; :X :Y :Z :AA :AB :AC :AD :AE :AF :AG :AH :AI :AJ :AK :AL :AM :AN :AO :AP
;; :AQ :AR :AS :AT :AU :AV :AW :AX :AY :AZ :BA :BB :BC :BD :BE :BF :BG :BH
;; :BI :BJ :BK :BL :BM :BN :BO :BP :BQ :BR :BS :BT :BU :BV :BW :BX :BY :BZ
;; :CA :CB :CC :CD :CE :CF :CG :CH :CI :CJ :CK :CL :CM :CN :CO :CP :CQ :CR
;; :CS :CT :CU :CV)
于 2012-07-18T00:01:38.603 に答える
4

コアカーションに不可欠なclojure機能(および「結び目を結ぶ」はそれに関するものですよね?)は反復されます。

(def abc (map (comp str char) (range 65 91)))
(defn cols [seed]
  (let [next #(for [x %] (for [y seed] (str x y)))]
    (->> (iterate #(apply concat (next %)) seed)
         (mapcat identity))))

(time (first (drop 475254 (cols abc))))
"Elapsed time: 356.879148 msecs"
"AAAAA"

(doc iterate)
-------------------------
clojure.core/iterate
([f x])
  Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects

編集:セットの「順序付けられた」サブセットを返す関数の一般化

(defn ordered-combinations [seed]
  (->> (map list seed)
       (iterate #(for [x % y seed] (concat x [y])))
       (mapcat identity)))

(def cols
  (let [abc (map char (range 65 91))]
    (map #(apply str %) (ordered-combinations abc))))

user> (take 30  (map #(apply str %) cols))
("A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z" "AA" "AB" "AC" "AD")
user> (take 28 (ordered-combinations [0 1]))
((0) (1) (0 0) (0 1) (1 0) (1 1) (0 0 0) (0 0 1) (0 1 0) (0 1 1) (1 0 0) (1 0 1) (1 1 0) (1 1 1) (0 0 0 0) (0 0 0 1) (0 0 1 0) (0 0 1 1) (0 1 0 0) (0 1 0 1) (0 1 1 0) (0 1 1 1) (1 0 0 0) (1 0 0 1) (1 0 1 0) (1 0 1 1) (1 1 0 0) (1 1 0 1))
于 2012-07-19T21:02:20.497 に答える
2

この答えは間違っています。うまくいけば、教育的な方法で。

数学的にあなたが求めているのは、アルファベットの無限シーケンスのすべてのサブセットの怠惰なシーケンスです。

(take 40 (map #(keyword (apply str %)) 
           (rest (combinatorics/subsets  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))))
(:A :B :C :D :E :F :G :H :I :J :K :L :M :N
 :O :P :Q :R :S :T :U :V :W :X :Y :Z :AB :AC 
 :AD :AE :AF :AG :AH :AI :AJ :AK :AL :AM :AN :AO)

foo.core> (nth (map #(keyword (apply str %)) 
                 (rest (combinatorics/subsets  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))) 
               40000)
:BLOUZ

project.clj:

(defproject foo "1.0.0-SNAPSHOT"
  :description "FIXME: write description"
  :dependencies [[org.clojure/clojure "1.3.0"]
                 [ org.clojure/math.combinatorics "0.0.3"]]
  :dev-dependencies [[swank-clojure/swank-clojure "1.4.0"]]) ; swank)

math.combanatoricsの使用:

(ns foo.core
  (:require [clojure.math.combinatorics :as combinatorics]))
于 2012-07-18T00:10:19.983 に答える
2

jneiraが述べたように、反復はこれを行う正しい方法のように感じます。

これは彼の機能の改善点であり、中間型が少ないため、より明確に理解できるはずです。ループ/繰り返しに基づく他のソリューションのいくつかとは異なり、完全に怠惰です。

(defn column-names-seq [alphabet]
  (->> (map str alphabet)
     (iterate (fn [chars]
                (for [x chars
                      y alphabet]
                  (str x y))))
     (apply concat)))

使用するには、アルファベットの文字列を指定するだけです。例:

(take 30 (column-names-seq "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))  ;; => ("A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z" "AA" "AB" "AC" "AD")
于 2014-05-27T13:59:04.437 に答える
1

これはあなたが探していたようなものかもしれないと思います(そうでない場合でも、少なくとも「正しい」答えはそうあるべきだと私は思っていました; o)。

(defn stream [seed]
  (defn helper [slow]
    (concat (map #(str (first slow) %) seed) (lazy-seq (helper (rest slow)))))
  (declare delayed)
  (let [slow (cons "" (lazy-seq delayed))]
    (def delayed (helper slow))
    delayed))

(take 25 (stream ["a" "b" "c"]))
("a" "b" "c" "aa" "ab" "ac" "ba" "bb" "bc" "ca" "cb" "cc" "aaa" "aab" "aac" "aba" "abb" "abc" "aca" "acb" "acc" "baa" "bab" "bac" "bba")

gitのコード。ひどく虐待しているのではないかと思いますdefが、うまくいきます。

考え方は非常に単純です。シーケンスから出力を取得し、それ自体にフィードバックします。出力(入力でもある)の値ごとに、シードシーケンスの各文字を追加して新しい出力を生成します。これは循環的であるため、継続します(入力には最初の「」がありますが、出力にはありません。これは、何もないところから何かを作成するのを防ぐのに役立ちます)。

出力を入力に供給するプロセスは、Haskellのかなり有名な論文では「結び目を結ぶ」と呼ばれています。しかし、Clojureは熱心な言語であるため(そして怠惰なシーケンスでさえ「十分に怠惰」ではないため)、Clojureで行うのは難しいです-私が見つけた唯一の解決策は、混乱することでしたdef(誰かがとでもっとうまくいくかもしれないと思いますdelayforce、私にはありませんでしたラック)。

そして多分それは地図として書くことさえできるでしょうか?

[よりコンパクトなコードで2012-07-19を更新]

Clojureの結び目を結ぶでの回答のはるかに優れたコードに関連する質問:(明示的、醜い)突然変異のない循環参照?(それはjneiraの答えと同じ考えです)。

完全を期すために、以下を使用した最終バージョンを示しiterateます。

(defn stream [seed]
  (defn helper [slow] (mapcat (fn [c] (map #(str c %) seed)) slow))
  (apply concat (iterate helper seed)))
于 2012-07-19T02:34:04.133 に答える
0

おそらく「for」の重複を削除する方法がありますが、これが私にとって有効なものです。

(def all-letters (map char (range 65 90)))
(defn kw [& args] (keyword (apply str args)))
(concat
  (for [l all-letters] (kw l))
  (for [l all-letters l2 all-letters] (kw l l2))
  (for [l all-letters l2 all-letters l3 all-letters] (kw l l2 l3)))
于 2012-07-17T22:49:48.793 に答える
-1
#include<stdio.h>
int main()
{
int n=703;

char arr[26]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};

while(n){
printf("%c ",arr[(n)%26]);
n=(n)/26;

}
return 0;
}

みんなこれはこれと同じくらい簡単ですか、それとも何かが足りないのですか....もちろん、上記のプログラムは必要なアトリングを逆に出力します。再帰を使用するか、文字列に格納して逆にすることで、それを回避できます...

于 2012-09-28T06:00:16.603 に答える