引数の1つに自身への呼び出しが含まれている場合にtrueを返す関数/マクロ


7

少なくとも1つの引数に関数自体への呼び出しが含まれている場合にのみ trueを返し、それ以外の場合はfalseを返す関数(またはマクロ)を記述します。

例えば:

int a=function(); //a==false
int b=function(0); //b==false
int c=function(function(0)); //c==true
int d=function(3*function(1)+2); //d==true (weakly-typed language)
bool e=function(true||function(1)); //e==true (strongly-typed language) 

編集:関数/マクロは他の補助関数/マクロを呼び出すことができます。

編集2:使用する言語がCのように動作しない限り、関数は少なくとも1つの引数を取る必要があります。ただし、引数を取らない関数は、それでも引数を指定して呼び出すことができます。


それはのようなコンテキストで動作するprint(func(), func(func()))必要がありますか、それとも関数が定義された直後に関数へのトップレベルの呼び出ししかありませんか?
algorithmhark

その状況で動作するはずです。

10
なぜそんなに早く受け入れる?
カイルカノス2014年

1
この質問は、実行時に式ツリーを確認できる言語でしか解決できないため、私はこの質問が嫌いです。
FUZxxl 2015

1
@FUZxxl:同意しません。呼び出しがFFIを介して間接的に行われる場合でも正常に機能する回答を投稿しました(したがって、内部関数の式ツリーを表示できません)。

回答:


11

Mathematica ...

... これのために作られました

SetAttributes[f, HoldAll]
f[x___] := ! FreeQ[Hold@x, _f]

f[]             (* False *)
f[0]            (* False *)
f[f[0]]         (* True *)
f[3 f[1] + 2]   (* True *)
f[True || f[1]] (* True *)

すべてが式であり、式にはヘッドといくつかの要素があります。だから、1+2実際にPlus[1,2]、そして{1,2}実際にありますList[1,2]。これは、関心のある頭の任意の式(この場合は関数f自体)と一致できることを意味します。

必要なのは、関数が呼び出される前にMathematicaが関数の引数を評価しないようにする方法を見つけることであり、それにより関数内の式ツリーを分析できます。何が何だHoldHoldAllのためです。Mathematica自体はこれを至る所で使用して、特定の実装に対して特別なケースを提供します。たとえば、呼び出しLength[Permutations[list]]た場合、実際にはこれらのすべての順列が作成されてメモリの負荷が無駄になることはありませんが、これを単にとして計算できることがわかりLength[list]!ます。

f[True || f[1]]例として最後の呼び出しを使用して、上記のコードを詳細に見てみましょう。通常、Mathematicaは最初に関数の引数を評価するので、これは単に短絡してを呼び出しますf[True]。ただし設定しました

SetAttributes[f, HoldAll]

これはMathematicaに引数を評価しないように指示するのでFullForm、呼び出しの(つまり、構文糖なしの内部式ツリー)は

f[Or[True,f[1]]]

そして、実際にはfこの形式で議論が受け入れられます。次の問題は、内fで、引数を使用するとすぐに、Mathematicaが再びそれを評価しようとすることです。これをローカルで抑制することができますHold@x(の構文糖衣Hold[x])。この時点で、元の式ツリーにハンドルがあり、必要に応じてそれを処理します。

式ツリーでパターンを検索するには、を使用できますFreeQ。これは、指定されたパターンが式ツリーで見つからないことを確認します。パターンを使用します。これは_f、任意の部分式とヘッドf(正確に私たちが探しているもの)を照合します。もちろん、FreeQ私たちが望むものの反対を返すので、結果を否定します。

もう1つ微妙です。引数をとして指定しましたx___。これは0個以上の要素のシーケンスです。これにより、f任意の数の引数で動作します。最初の呼び出しでは、f[]これはHold@x単にになることを意味しますHold[]。のようf[0,f[1]]に複数の引数がある場合は、にHold@xなりますHold[0,f[1]]

これですべてです。


6

C ++ 11

式テンプレートと同様に、関数のパラメーターリスト内の関数をその戻り値の型で呼び出したという事実を伝えることができます。

最初に、いくつかのヘルパークラスと関数が必要です。

#include <iostream>

template <bool FunctionWasInParameters> struct FunctionMarker {
  operator bool() const { return FunctionWasInParameters; }

  operator int() const { return FunctionWasInParameters; }
};

template <bool... values> struct Or;

template <bool first, bool... values> struct Or<first, values...> {
  static constexpr bool value = first || Or<values...>::value;
};

template <> struct Or<> { static constexpr bool value = false; };

template <class T> struct is_FunctionMarker {
  static constexpr bool value = false;
};

template <bool B> struct is_FunctionMarker<FunctionMarker<B>> {
  static constexpr bool value = true;
};

#define OVERLOAD_OPERATOR_FOR_FUNCTION_MARKER(OPERATOR)                        \
  template <bool B, class T>                                                   \
  FunctionMarker<B> operator OPERATOR(FunctionMarker<B>, T) {                  \
    return {};                                                                 \
  }                                                                            \
  template <bool B, class T>                                                   \
  FunctionMarker<B> operator OPERATOR(T, FunctionMarker<B>) {                  \
    return {};                                                                 \
  }                                                                            \
  /* to break ambiguity by specialization */                                   \
  template <bool B, bool B2>                                                   \
  FunctionMarker<B || B2> operator OPERATOR(FunctionMarker<B>,                 \
                                            FunctionMarker<B2>) {              \
    return {};                                                                 \
  }

OVERLOAD_OPERATOR_FOR_FUNCTION_MARKER(|| )
OVERLOAD_OPERATOR_FOR_FUNCTION_MARKER(+)
OVERLOAD_OPERATOR_FOR_FUNCTION_MARKER(*)
// TODO: overload all other operators!

これで、質問とまったく同じコードに使用できます。

template <class... Args>
auto function(Args... args)
    -> FunctionMarker<Or<is_FunctionMarker<Args>::value...>::value> {
  return {};
}

FunctionMarker<false> function() { return {}; }

int main() {
  int a = function();
  int b = function(0);
  int c = function(function(0));
  int d = function(3 * function(1) + 2);
  bool e = function(true || function(1));

  // clang-format off
  std::cout << a << "//a==false\n"
            << b << "//b==false\n"
            << c << "//c==true\n"
            << d << "//d==true (weakly-typed language)\n"
            << e << "//e==true (strongly-typed language)\n";
}

ideoneからの出力:

0//a==false
0//b==false
1//c==true
1//d==true (weakly-typed language)
1//e==true (strongly-typed language)

4

C#

public PcgBool f(params object[] args)
{
    return args.Any(p => p is PcgBool);
}

public class PcgBool
{
    public PcgBool() { }
    public PcgBool(bool value)
    {
        Value = value;
    }

    private bool Value;

    public static implicit operator bool(PcgBool pcgBool)
    {
        return pcgBool.Value;
    }    

    public static implicit operator PcgBool(bool value)
    {
        return new PcgBool(value);
    }
}

使用法LINQPadで):

void Main()
{
    Console.WriteLine(f(1,2,f(3),4)); // True
    Console.WriteLine(f(1,2,3,"4")); // False
}

ここでの秘訣は、ブールのようなfカスタムタイプ(PcgBool)を渡すことで、パラメーターをより認識させることです。

PS私は、boolとの間で暗黙的にキャスト可能なカスタム型を返すことが不正行為と見なされないことを願っています。技術的には、ブール値であるかのように戻り値を使用できます。また、「もしある場合にのみtrueを返す」などの質問が返されますが、戻り値のタイプはブール値である必要はありません。


どうf(new PcgBool())ですか?
Qwertiy、2015

うーん...あなたはそれについて正しいです。それは私の答えを壊すように見えます。残念ながら、私は今までにそれを修正するのが面倒です(久しぶりです...)
Jacob

3

ルア

local x
local function f()
    local y = x
    x = true
    return y
end
debug.sethook(function()
        if debug.getinfo(2).func ~= f then
            x = false
        end
    end, "l")
print(f())
print(f(0))
print(f(f()))
print(f(f(0)))
print(f("derp" .. tostring(f())))

そして、テーブルを再帰的に比較する方法を考えていました。よくできました。デバッグがそれほど強力になるとは思いませんでした。
yyny

3

C ++ 11 TMP

これは少し長いです。C ++テンプレートにはいくつかの制限があるため、すべてを型で処理する必要がありました。したがって、「True」とその数値は、boolとintに変換されました。また、演算+、-、|| add、mul、or_に変更されました。

これが有効な回答となることを願っています。

template <typename... Args>
struct foo;

template <>
struct foo<>
{
    static bool const value = false;
};

template <typename T>
struct is_foo
{
    static bool const value = false;
};

template <typename... Args>
struct is_foo<foo<Args...>>
{
    static bool const value = true;
};

template <typename T>
struct is_given_foo
{
    static bool const value = false;
};

template <template <typename...> class T, typename... Args>
struct is_given_foo<T<Args...>>
{
    static bool const value = foo<Args...>::value;
};

template <typename Head, typename... Tail>
struct foo<Head, Tail...>
{
    static bool const value = is_foo<Head>::value || is_given_foo<Head>::value || foo<Tail...>::value;
};

template <typename... Args>
struct add {};

template <typename... Args>
struct mul {};

template <typename... Args>
struct or_ {};

static_assert(foo<>::value == false, "int a=function(); //a==false");
static_assert(foo<int>::value == false, "int b=function(0); //b==false");
static_assert(foo<foo<int>>::value == true, "int c=function(function(0)); //c==true");
static_assert(foo<add<mul<int, foo<int>>, int>>::value == true, "int d=function(3*function(1)+2); //d==true (weakly-typed language)");
static_assert(foo<or_<bool,foo<int>>>::value == true, "bool e=function(true||function(1)); //e==true (strongly-typed language)");

// just for the sake of C++
int main()
{
    return 0;
}

すごくいい!の2番目の定義がis_given_foo最初の定義よりも優先されるのはどのルールですか?
feersum

標準で引用する適切な場所を見つけることができなかったので、誰かが助けてくれるかもしれません。とにかく、2番目のis_given_fooは最初のテンプレートの特殊化であるため、テンプレートパラメーターが指定されたパターンと一致する場合、パラメーターがテンプレート自体の場合は常に推奨されます。
Felix Bytow、2015

2

C

プロシージャでそれができるとは思いませんが、マクロはいつでも(乱用)できます。

#include <stdio.h>
#define f(x) ((max_depth = ++depth), (x), (depth-- < max_depth))

int depth = 0;
int max_depth = 0;

char* bool(int x) { // Helper - not necessary for solution
  return x ? "true" : "false";
}

int main() {
  printf("f(1): %s\n", bool(f(1)));
  printf("f(f(1)): %s\n", bool(f(f(1))));
  printf("f(bool(f(1))): %s\n", bool(f(bool(f(1)))));
  printf("f(printf(\"f(1): %%s\\n\", bool(f(1)))): %s\n", bool(printf("f(1): %s\n", bool(f(1)))));
}

これは出力します:

f(1): false
f(f(1)): true
f(bool(f(1))): true
f(1): false
f(printf("f(1): %s\n", bool(f(1)))): true

マクロfは、現在の深度と、それが呼び出されてから達成された最大深度を追跡します。後者が前者より大きい場合は、再帰的に呼び出されています。


へえ。最終的に、多かれ少なかれ同じ時間でほぼ同じソリューションが得られました。
アート

@Art LOL。また、私はカンマ演算子を認識していなかったとして、現在、非常に愚かな感じ、私が使用して周りのハッキング、(私の第四または第五の選択言語の周りのCのどこかから)&&||。私は私の答えを引き換えようとするかもしれません。
James_pic 2014年

まあ、コンマ演算子は難読化の追加の層のためだけです。通常のコードでは決して使用しません。しかし、この場合、論理演算子を使用しようとしたときに混乱しました。
アート

2

C、13

#define F(X)0

引数は展開されないため、マクロを呼び出すことはできません。それは単なる平文の束にすぎません。したがって、答えは常に偽です。


1
これは本当に素晴らしい答えです。
FUZxxl 2015

古いプリプロセッサの投稿を見ているときにこれに遭遇しました...実際、これは間違っています。 F(F(0))喜んで最初にFの引数を評価しますF(0)。その引数は0に展開されます。次に、引数0に青色のペイントなしでFを評価し、結果として0になります。非再帰的な制限は適用されません。私が持っているなどのこと#define F(X) G#define G F(Y)遊びです。で、この場合、一方 GにF(0)を拡張し、次にF(Y)に、トークンFが現れます。現在 Fを展開しているので、この場合、Fは青色のペイントであり、展開はF(Y)で停止します。
Hウォルターズ

@HWaltersうわー、あなたは正しいです。私の新しい説明についてどう思いますか?
feersum

つまり、これXは引数置換リストにないため、バインドされているマクロは展開されないということです。これを関数が呼び出されていると解釈すると、引数の関数が呼び出されることはありません。はい、そうだと思います。
Hウォルターズ

1

C

#include <stdio.h>

int a, b;
#define foo(x) (b=a++,(void)x,a--,!!b)

int
main(int argc, char **argv)
{
        printf("%d\n", foo(1));
        printf("%d\n", foo(0));
        printf("%d\n", foo(foo(1)));
        printf("%d\n", foo(foo(foo(1))));
        return 0;
}

マクロで再帰の深さを数えることができます。次に、内部マクロで外部マクロの戻り値を上書きします。!!b戻り値をブール値に正規化することです。前処理されたコードは次のようになります。

int a, b;

int
main(int argc, char **argv)
{
 printf("%d\n", (b=a++,(void)1,a--,!!b));
 printf("%d\n", (b=a++,(void)0,a--,!!b));
 printf("%d\n", (b=a++,(void)(b=a++,(void)1,a--,!!b),a--,!!b));
 printf("%d\n", (b=a++,(void)(b=a++,(void)(b=a++,(void)1,a--,!!b),a--,!!b),a--,!!b));
 return 0;
}

何の(確かに非常に愚かな)ケースについてprintf("%d\n", foo(printf("%d\n", foo(1))))。の内部呼び出しfooは1 を返しますが、は呼び出しませんfoo
James_pic 14年

1

C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BLAH(x) (strncmp( "BLAH(", #x, strlen("BLAH(")) == 0)

int main(int argc, char** argv)
{
  printf("%d\n", BLAH(1));
  printf("%d\n", BLAH("1234"));
  printf("%d\n", BLAH("BLAH"));
  printf("%d\n", BLAH(BLAHA));
  printf("%d\n", BLAH(BLAHB()));
  printf("%d\n", BLAH(BLAH));
  printf("%d\n", BLAH(BLAH()));
  printf("%d\n", BLAH(BLAH("1234")));
  return 0;
}

マクロは、引数が「BLAH(」で始まるかどうかを比較します。


1
上では動作しませんBLAH(blub(BLAH(0)))
FUZxxl 2015

1

アルゴール60

ここにboolean procedure質問が求めることを行うa があります(注:Algol 60はトークンのリストに関して定義されており、構文は修正されていません。以下では、プログラムを構成する個々のトークンを表すためにMarst構文を使用しています):

boolean procedure recursion detector(n);
  boolean n;
  begin
    own boolean nested, seen nested;
    boolean was nested, retval;
    was nested := nested;
    begin if nested then seen nested := true end;
    nested := true;
    retval := n; comment "for the side effects, we ignore the result";
    nested := was nested;
    retval := seen nested;
    begin if ! nested then seen nested := false end;
    recursion detector := retval
  end;

検証

これが私が使ったテストコードです:

procedure outboolean(c, b);
  integer c;
  boolean b;
  begin
    if b then outstring(c, "true\n") else outstring(c, "false\n")
  end;

begin
  outboolean(1, recursion detector(false));
  outboolean(1, recursion detector(true));
  outboolean(1, recursion detector(recursion detector(false)));
  outboolean(1, recursion detector(false | recursion detector(true)));
  outboolean(1, recursion detector(false & recursion detector(true)));
  outboolean(1, recursion detector(recursion detector(recursion detector(false))))
end

予想通り、出力は次のとおりです。

false
false
true
true
true             comment "because & does not short-circuit in Algol 60";
true

説明

Algol 60は、ほとんどの言語とは異なる評価順序を持っています。これは独自のロジックを備えており、実際には一般的な評価順序よりもはるかに強力で一般的ですが、人間が頭を回すのはかなり困難です(また、コンピューターを効率的に実装するため、Algol 68)で変更されました。これにより、不正行為のないソリューションが可能になります(プログラムは解析ツリーなどを調べる必要がありません。また、ここにある他のほとんどすべてのソリューションとは異なり、ネストされた呼び出しがFFI)。

私はまた、言語のいくつかの癖を自慢することを決めました。(特に、変数名には空白を含めることができます。アンダースコアを含めることができないため、これは読みやすくするのにかなり役立ちます。コメントインジケーターがcommentほとんどの構文エンコーディングのリテラルワードであるという事実も気に入ってます。Algol68は、これを略して扱いにくいと感じました。コメントと¢代替として紹介します。コメント本文を囲む引用符は通常は必要ありません。わかりやすくするため、およびセミコロンを入力したときにコメントが誤って終了しないようにするために、引用符を追加します。)言語の幅広い概念が本当に好きです(詳細でない場合)、しかしそれは私がPPCGでそれを使用することはめったにないほど冗長です。

Algol 60がインスピレーションを得た言語と異なる主な方法(Algol 68、間接的にC、Javaなど。K&R Cを知っている人は、おそらく関数のこの構文を認識するでしょう)は、関数の引数が少し似ていることです。独自の小さなラムダ。たとえば、55という数値だけの関数に引数を指定した場合、引数x+1を指定すると、指定したとおりx結果が得xられます。つまり、プラス1の結果ではなく、「プラス1」の概念になります。場合ということですx変更は、その後、評価しようとし、当該関数の引数が表示されます新しいのの値をx。関数の引数が関数の内部で評価されない場合、関数の外部でも評価されません。同様に、それが関数内で複数回評価される場合、それは毎回別々に評価されます(これは最適化できないと仮定します)。これは、たとえば、関数内で、ifまたは関数内で機能をキャプチャすることなどが可能であることを意味しwhileます。

このプログラムでは、関数の呼び出しがその関数の引数に現れた場合、その関数は再帰的に実行されるという事実を利用しています(引数は、関数が評価するポイントで正確に評価されるため) 、以前も後もない。これは必ずしも関数本体の内部にある必要がある)。これにより、関数が再帰的に実行されているかどうかを検出するという問題が軽減され、はるかに簡単になります。必要なのは、再帰呼び出しがあるかどうかを検出するスレッドローカル変数(さらに、この場合、別の方法で情報をやり取りするための別の呼び出し)です。静的変数(つまり、own)目的のため、Algol 60はシングルスレッドです。その後に行う必要があるのは、すべてを元の状態に戻すことです。これにより、関数が複数回呼び出された場合に正しく機能します(PPCGルールで必要な場合)。

この関数は、現時点では内部呼び出しから望ましい値を返しません(少なくとも、自分自身を数えるのではなく引数のみで自己呼び出しを探す必要があると仮定した場合)。その作業を行うことは、同じ一般的な原則を使用するとかなり簡単ですが、より複雑であり、機能の動作がわかりにくくなります。それが質問に準拠するために必要であると思われる場合、変更することはそれほど難しくないはずです。


0

ジャワ

public class FuncOFunc{

private static int count = 0;

public static void main(String[] args){

    System.out.println("First\n" + function());
    reset();

    System.out.println("Second\n" + function(1));
    reset();

    System.out.println("Third\n" + function(function(1)));
    reset();

    System.out.println("Fourth\n" + function(3*function(1)+2));
    reset();

    System.out.println("Fifth\n" + function(function(1), function(), 4));
}

/**
 * @param args
 */
private static int function(Object...args) {
    StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
    count+=stackTraceElements.length;
    if(count>3) return 1;
    else return 0;
}

static void reset(){
    count = 0;
}
}

reset()補助として数えることができますか?

出力:

First
0
Second
0
Third
1
Fourth
1
Fifth
1

編集

これは、reset()メソッドを使用しない別のバージョンですが、狂気の多くです。これは、stdinの引数として渡された関数への呼び出しを使用して、上記のコードを実行時に作成およびコンパイルします。私はもっ​​とエレガントな解決策が欲しかったのですが、残念なことにこれに時間をかけすぎていません:(

これを実行するには、たとえば、次を呼び出しますjavac FuncOFunc.java function(function(1),function(),4)

import java.io.File;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLClassLoader;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class FuncOFunc {
    public static void main(String[] args) throws Exception {
        JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager sjfm = jc.getStandardFileManager(null, null, null);
        File jf = new File("FuncOFuncOFunc.java");
        PrintWriter pw = new PrintWriter(jf);
        pw.println("public class FuncOFuncOFunc{"
                + "public static void main(){ "
                + "     System.out.println("+ args[0] +");"
                + "}"
                + "     private static int function(Object...args)     {"
                + "         StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();"
                + "         if(stackTraceElements.length>3) return 1;"
                + "         else return 0;"
                + "     }"
                + "}");
    pw.close();
    Iterable<? extends JavaFileObject> fO = sjfm.getJavaFileObjects(jf);
    if(!jc.getTask(null,sjfm,null,null,null,fO).call()) {
        throw new Exception("compilation failed");
    }
    URL[] urls = new URL[]{new File("").toURI().toURL()};
    URLClassLoader ucl = new URLClassLoader(urls);
    Object o= ucl.loadClass("FuncOFuncOFunc").newInstance();
    o.getClass().getMethod("main").invoke(o);
    ucl.close();
}
}

呼び出しのreset()たびに使用法を強制できるとは思いませんfunction。補助関数のアイデアは、functionの本体内から他のプライベートメソッドを呼び出すことができるようにすることです...しかし、それは私の質問の私の解釈にすぎません。
Jacob

私も同じ気持ちです... OPがこの点を明らかにするのを待ちましょう。その間私はreset()より少ないバージョンのために働いています。それでも、上記のコードは、メインにコールが1つしかない場合(変数countとリセット関数なし)に機能します
Narmer

1
明快さの欠如について申し訳ありませんが、私はジェイコブが補助機能によって言ったことを意味しました。また、最初に書いたコードは、function()だけでなく、メソッドがfunction(...)内で呼び出された場合に「true」を返しますね。

あなたの編集は、私が今まで見た中で最悪のコードでなければなりません。+1を持っている。
ランチャー2014年

あはは!ありがとう!それは、創造性がなく、時間もほとんどない状態でクリエイティブにしようとするとどうなるかです...それはおそらく、私がJavaでこれまで作った中で最悪のものです。それでもコンパイルします!
Narmer、2014年

0

パイソン

import ast, inspect

def iscall(node, name, lineno=None):
    return isinstance(node, ast.Call) \
            and (node.lineno == lineno or lineno is None) \
            and hasattr(node.func, 'id') \
            and node.func.id == name

def find_call(node, name, lineno):
    for node in ast.walk(node):
        if iscall(node, name, lineno):
            return node

def is_call_in_args(call):
    descendants = ast.walk(call);
    name = next(descendants).func.id
    return any(map(lambda node: iscall(node, name), descendants))

def function(*args):
    this = inspect.currentframe()
    _, _, funcname, _, _ = inspect.getframeinfo(this)
    outer = inspect.getouterframes(this)[1]
    frame, filename, linenum, _, context, cindex = outer
    module = ast.parse(open(filename).read())
    call = find_call(module, funcname, linenum)
    return is_call_in_args(call)

if __name__ == '__main__':

    print("Works with these:")
    assert(function() == False)
    assert(function(3*function(1)+2) == True)
    assert(function(0) == False)
    assert(function(function(0)) == True)
    assert(function(True or function(1) == True))

    print("Does not work with multiple expressions on the same line:")
    assert(function(function()) == False); function()
    function(); assert(function(function()) == False)

名前を付けて保存し、別のスクリプトでselfarg.py実行しfrom selfarg import functionます。replでは機能しません。

現在および外部のスタックフレームを使用するとfunction、その名前と呼び出し場所(ファイルと行番号)が取得されます。次に、取得したファイルを開き、解析して抽象構文ツリーにします。行番号で識別される関数呼び出しにスキップし、引数に同じ名前の別の関数呼び出しがあるかどうかを検査します。

編集:python2でも問題ありません。タイトルのpython3をpythonに変更しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.