プロが教えるわが家の防犯対策術!

指定した文字をランダムに表示するプログラムを組みました。

using System;
using System.Linq;

namespace ランダム文字列
{
class Program
{
static void Main(string[] args)
{
var characters = "TJIOZLS";
var Charsarr = new char[7];
var random = new Random();

for (int i = 0; i < Charsarr.Length; i++)
{
Charsarr[i] = characters[random.Next(characters.Length)];
}

var resultString = new String(Charsarr);
Console.WriteLine(resultString);
}
}
}

上記のプログラムだと1回分表示されますが、10回分のランダムな文字列を表示させるようにするにはどうすればいいですか?また、それらの文字列が被らないようにすることは可能ですか?

質問者からの補足コメント

  • 10回やればいいのは普通に思い付きますが短くする方法があればそっちをやりたいですし、同じものが出たら却下する方法が知らないので質問してます。それくらい考えてください。

    No.2の回答に寄せられた補足コメントです。 補足日時:2021/06/24 19:55

A 回答 (4件)

さて、人類史上最強のプログラミング言語Lispですが。


いきなり、説明の為とは言え、プログラミング初心者にLispのコードを見せてもビビるだけ、なんですよね。人によっては失禁したりウンコを漏らしたりする。
まぁ、当然と言えば当然で、RPGで言うと最初の村なり街から出た途端にラスボスの魔王に遭遇するようなモンです。フツーは泣いちゃいます。

と言うわけで、C#は相変わらず良く分からんので、C#に似てるプログラミング言語、Javaで書いてみますか。
発想はLispで書いたコードと全く同じです。が、やっぱ見た目は違いますね。

// ここから

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Program {
 public static void main(String[] args) {
  String characters = "TJIOZLS";
  char[] Charsarr = new char[7];
  Random random = new Random();
  // ここで C# でも可変長のリスト resultStrings を用意する
  List<String> resultStrings = new ArrayList<String>();

  // リスト resultStrings の大きさが 10 になるまで繰り返す
  while (resultStrings.size() != 10) {
   for (int i = 0; i < Charsarr.length; i++) {
    Charsarr[i] = characters.charAt(random.nextInt(characters.length()));
   }
   String resultString = new String(Charsarr);
   // ここで C# でも Any を使って resultString が既にリスト resultStrings
   // に含まれるか調べよう
   if (resultStrings.stream().anyMatch(x -> x.equals(resultString))) {
    // 含まれてた場合、resultStringを廃棄して while の先頭に戻る
    continue;
   } else {
    // 含まれてなかった場合、リスト resultStrings に resultString を
    // 追加する
    resultStrings.add(resultString);
   }
  }
  // 残りは出力のみ
  for (String resultString: resultStrings) {
   System.out.println(resultString);
  }
 }
}

// ここまで

もう一回書いておきますが、ポイントは以下の2つです。

1. 得た結果を保持するアキュムレータ(累積器)を可変長のリストで作成する。上のコード上はresultStringsと言う文字列のリストになってて、最初は空リストである。
2. 乱数によって発生した文字列がアキュムレータの中に既にあるかどうかは、Lispではmember関数で判定していた。上のコードではJava8以降に含まれるanyMatchメソッドで代用している。C#だと恐らくAnyを適用すれば良い筈。
アキュムレータに得たresultStringが存在してた場合は何もしない。そうじゃない場合はアキュムレータresultStringsにresultStringを追加(通常pushと呼んだりする)すれば良い。
    • good
    • 0

> Lisp系言語だとmemberって関数があって、結果リストの要素と作った文字列が一致した場合、とか検査出来るんだけどC#でそういう便利な組み込み関数があるかどうか知らん



C#だとこれかな?

JavaScript 屋さんのための C# LINQ 入門 (3) every / All と some / Any:
https://mseeeen.msen.jp/linq-basic-for-javascrip …

例えばLisp系言語だと、次のようなリストがあったとして。

> (define resultStrings '("hoge" "fuga" "piyo"))
> resultStrings
'("hoge" "fuga" "piyo")
>

"fuga"がresultStringに含まれるかどうか調べる際にmemberを用います。

> (member "fuga" resultStrings)
'("fuga" "piyo")

Lispの場合、上のように調べた要素を先頭とするサブリストを返してきたりするんですが、いずれにせよ「発見しました」って情報を返してくるんですね。
一方、要素が無い場合、

> (member "foo" resultStrings)
#f

と言うように偽値を返してきます。
真偽値自体の表現はプログラミング言語によって変わってきますが、やってるこたぁ変わらない。
いずれにせよ、C#でAnyメソッド(かな?)が同様の事柄を実行するのなら、resultStringを詰め込んだresultStringsを(例えばListを使って)作って、それにAnyメソッドを適用して判定すれば良いんじゃないかしらん。
    • good
    • 0

とは言っても、要繰り返し、になるんじゃないかしらん。



Lisp系言語だとmemberって関数があって、結果リストの要素と作った文字列が一致した場合、とか検査出来るんだけどC#でそういう便利な組み込み関数があるかどうか知らんし・・・。最悪自作するしかないかなぁ。

んで、

> 10回分のランダムな文字列を表示させる

には10回繰り返すよりも、解を保持するアキュムレータを可変長のリストかなんかにして、長さが10になった時点で終了させる、とかそういう方法になるんじゃないかしらん。

;; Lisp系言語Schemeでの例

(define (program)
 (let ((characters "TJIOZLS"))
  (let loop ((resultStrings '()))
   (if (= (length resultStrings) 10)
    (for-each (lambda (x) (display x) (newline)) resultStrings)
    (let ((resultString (list->string
               (let recur ((Charsarr '()))
                (if (= (length Charsarr)
                   (string-length characters))
                  (reverse Charsarr)
                 (recur (cons (string-ref
                        characters
                        (random (string-length characters)))
                       Charsarr)))))))
     (loop (if (member resultString resultStrings)
          resultStrings
          (cons resultString resultStrings))))))))

;;; ここまで

まぁ、Javaに比べると参考にはならんでしょうけどね(一応変数名は合わせてますが、結果やっぱり二重ループになってます)。
    • good
    • 0

「10回分表示させたい」なら 10回やればいいし, 「文字列が被らないようにしたい」なら覚えておいて同じものが出たら却下すればいい

.
この回答への補足あり
    • good
    • 1

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!