見出し画像

いろいろなAIにコーディングさせて遊んでみた

ChatGPTにプログラミングさせて遊んでみたばかりだけど、

ちょっと思いついたので、さらに遊んでみることにします。
いろいろな対話型AIがあるが、それによってコーディングは変わるのか?を試してみたい、と思いました。

プロンプト

プロンプトとしては以下を考えてみました。

C#で構造体をコーディングしたい。

#仕様
- 1月から12月を示す Month型の静的なプロパティを持つ。
- IEnumerable<Month> インターフェイスを実装
- IEquable<Month> インターフェイスを実装
- IComparabe, IComparable<Month> インターフェイスを実装
- IConvertible インターフェイスを実装
- IFormattable インターフェイスを実装
- Addメソッド:引数分の月数経過後の月を示す Month型の値を返す
- int型に暗黙的にキャストできるようにする。
- Month型同士を比較演算子で比較できるようにする

#条件
- C#のバージョンは 9.0 以降
- 初期化で型名が省略できる場合やラムダ式で住む場合など、より短い記述ができる場合はそのように記述する
- 上記の仕様を満たす目的以外の変数、プロパティ、メソッドなどは記述しない

今回使用するAIにBardも入れているので、日本語対応できていないこともあり、上記プロンプトを英訳し、英語のプロンプトで試してみることにします。
DeepLで英訳したものを少々修正したものが以下

I want to code structures in C#.

#Specification.
- Has a static property of type Month indicating January through December.
- Implement IEnumerable<Month> interface
- Implement IEquable<Month> interface
- implements IComparabe and IComparable<Month> interface
- Implement IConvertible interface
- Implement IFormattable interface
- Add method: returns a value of type Month indicating the month after the argument number of months has elapsed.
- Allow implicit cast to int type.
- Allows Month types to be compared with each other using the comparison operator

#Conditions
- C# version 9.0 or later
- If a shorter description is possible, such as when the type name can be omitted in initialization or when living in a lambda expression, it should be described as such.
- Do not describe variables, properties, methods, etc. other than for the purpose of satisfying the above specifications.

出力されたコーディング

ChatGPT

using System;
using System.Collections;
using System.Collections.Generic;

public class Month
    : IEnumerable<Month>,
        IEquatable<Month>,
        IComparable,
        IComparable<Month>,
        IConvertible,
        IFormattable
{
    private static readonly Month[] Months =
    {
        new Month("January", 1),
        new Month("February", 2),
        new Month("March", 3),
        new Month("April", 4),
        new Month("May", 5),
        new Month("June", 6),
        new Month("July", 7),
        new Month("August", 8),
        new Month("September", 9),
        new Month("October", 10),
        new Month("November", 11),
        new Month("December", 12)
    };

    private readonly string _name;
    private readonly int _number;

    private Month(string name, int number)
    {
        _name = name;
        _number = number;
    }

    public static Month January => Months[0];
    public static Month February => Months[1];
    public static Month March => Months[2];
    public static Month April => Months[3];
    public static Month May => Months[4];
    public static Month June => Months[5];
    public static Month July => Months[6];
    public static Month August => Months[7];
    public static Month September => Months[8];
    public static Month October => Months[9];
    public static Month November => Months[10];
    public static Month December => Months[11];

    public static implicit operator int(Month month)
    {
        return month._number;
    }

    public Month AddMonths(int months)
    {
        int newMonthNumber = (_number - 1 + months) % 12 + 1;
        return Months[newMonthNumber - 1];
    }

    public bool Equals(Month other)
    {
        return _number == other?._number;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj))
            return false;
        return obj is Month month && Equals(month);
    }

    public override int GetHashCode()
    {
        return _number;
    }

    public IEnumerator<Month> GetEnumerator()
    {
        return ((IEnumerable<Month>)Months).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public int CompareTo(object obj)
    {
        if (obj == null)
            return 1;
        if (!(obj is Month))
            throw new ArgumentException("Object is not a Month");
        return CompareTo((Month)obj);
    }

    public int CompareTo(Month other)
    {
        if (other == null)
            return 1;
        return _number.CompareTo(other._number);
    }

    public TypeCode GetTypeCode()
    {
        return TypeCode.Object;
    }

    public bool ToBoolean(IFormatProvider provider)
    {
        return _number != 0;
    }

    public byte ToByte(IFormatProvider provider)
    {
        return (byte)_number;
    }

    public char ToChar(IFormatProvider provider)
    {
        return Convert.ToChar(_number);
    }

    public DateTime ToDateTime(IFormatProvider provider)
    {
        throw new InvalidCastException();
    }

    public decimal ToDecimal(IFormatProvider provider)
    {
        return _number;
    }

    public double ToDouble(IFormatProvider provider)
    {
        return _number;
    }

    public short ToInt16(IFormatProvider provider)
    {
        return (short)_number;
    }

    public int ToInt32(IFormatProvider provider)
    {
        return _number;
    }

    public long ToInt64(IFormatProvider provider)
    {
        return _number;
    }

    public sbyte ToSByte(IFormatProvider provider)
    {
        return (sbyte)_number;
    }

    public float ToSingle(IFormatProvider provider)
    {
        return _number;
    }

    public string ToString(string format, IFormatProvider formatProvider)
    {
        if (string.IsNullOrEmpty(format))
        {
            return _name;
        }
        if (formatProvider == null)
        {
            formatProvider = System.Globalization.CultureInfo.CurrentCulture;
        }
        string formatString = format.ToUpperInvariant();
        switch (formatString)
        {
            case "N":
                return _name;
            case "M":
                return _number.ToString(formatProvider);
            case "MN":
                return $"{_number.ToString(formatProvider)} {_name}";
            default:
                throw new FormatException($"Invalid format string: '{format}'");
        }
    }

    public object ToType(Type conversionType, IFormatProvider provider)
    {
        if (conversionType == typeof(int))
        {
            return _number;
        }
        throw new InvalidCastException();
    }

    public ushort ToUInt16(IFormatProvider provider)
    {
        return (ushort)_number;
    }

    public uint ToUInt32(IFormatProvider provider)
    {
        return (uint)_number;
    }

    public ulong ToUInt64(IFormatProvider provider)
    {
        return (ulong)_number;
    }

    public static bool operator ==(Month left, Month right)
    {
        if (ReferenceEquals(left, right))
        {
            return true;
        }
        if (left is null || right is null)
        {
            return false;
        }
        return left._number == right._number;
    }

    public static bool operator !=(Month left, Month right)
    {
        return !(left == right);
    }

    public static bool operator <(Month left, Month right)
    {
        return left?._number < right?._number;
    }

    public static bool operator >(Month left, Month right)
    {
        return left?._number > right?._number;
    }

    public static bool operator <=(Month left, Month right)
    {
        return left?._number <= right?._number;
    }

    public static bool operator >=(Month left, Month right)
    {
        return left?._number >= right?._number;
    }
}

構造体(struct)ではなくクラス(class)となっています。「構造体をコーディング」は指示文ではなく、仕様などに入れたほうが良かったかも。
より短い記述をお願いしたつもりだったが、ラムダ式などは使われませんでした。
Addというメソッドを追加するつもりだったが、英訳した段階で "Add method" (メソッドを追加)となったため、メソッド名はAIが考えたもの(ここではAddMonths)となったようです。まぁ、これはいいでしょう。

Bard

Draft1

using System;

public struct Month
{
    private static readonly Month[] months = new Month[]
    {
        new Month(1, "January"),
        new Month(2, "February"),
        new Month(3, "March"),
        new Month(4, "April"),
        new Month(5, "May"),
        new Month(6, "June"),
        new Month(7, "July"),
        new Month(8, "August"),
        new Month(9, "September"),
        new Month(10, "October"),
        new Month(11, "November"),
        new Month(12, "December")
    };

    private readonly int monthNumber;
    private readonly string monthName;

    public Month(int monthNumber, string monthName)
    {
        this.monthNumber = monthNumber;
        this.monthName = monthName;
    }

    public static Month January => months[0];
    public static Month February => months[1];
    public static Month March => months[2];
    public static Month April => months[3];
    public static Month May => months[4];
    public static Month June => months[5];
    public static Month July => months[6];
    public static Month August => months[7];
    public static Month September => months[8];
    public static Month October => months[9];
    public static Month November => months[10];
    public static Month December => months[11];

    public int MonthNumber => monthNumber;
    public string MonthName => monthName;

    public static IEnumerable<Month> Enumerate() => months;

    public static bool operator ==(Month left, Month right) => left.monthNumber == right.monthNumber;
    public static bool operator !=(Month left, Month right) => !(left == right);
    public static int CompareTo(Month left, Month right) => left.monthNumber - right.monthNumber;

    public static implicit operator int(Month month) => month.monthNumber;

    public Month AddMonths(int months)
    {
        if (months < 0)
        {
            throw new ArgumentOutOfRangeException(nameof(months), "months must be non-negative");
        }

        int newMonthNumber = monthNumber + months;
        if (newMonthNumber > 12)
        {
            newMonthNumber -= 12;
        }

        return months[newMonthNumber];
    }

    public override bool Equals(object obj) => obj is Month other && Equals(other);
    public override int GetHashCode() => monthNumber;
    public override string ToString() => monthName;
}

Draft2

// C# Month structure

public struct Month : IEquatable<Month>, IComparable<Month>, IConvertible, IFormattable
{
    public static readonly Month January = new Month(1);
    public static readonly Month February = new Month(2);
    public static readonly Month March = new Month(3);
    public static readonly Month April = new Month(4);
    public static readonly Month May = new Month(5);
    public static readonly Month June = new Month(6);
    public static readonly Month July = new Month(7);
    public static readonly Month August = new Month(8);
    public static readonly Month September = new Month(9);
    public static readonly Month October = new Month(10);
    public static readonly Month November = new Month(11);
    public static readonly Month December = new Month(12);

    private readonly int monthNumber;

    public Month(int monthNumber)
    {
        if (monthNumber < 1 || monthNumber > 12)
        {
            throw new ArgumentOutOfRangeException("monthNumber");
        }

        this.monthNumber = monthNumber;
    }

    public int MonthNumber
    {
        get { return this.monthNumber; }
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
        {
            return false;
        }

        if (obj.GetType() != typeof(Month))
        {
            return false;
        }

        return this.Equals((Month)obj);
    }

    public bool Equals(Month other)
    {
        if (other == null)
        {
            return false;
        }

        return this.monthNumber == other.monthNumber;
    }

    public override int GetHashCode()
    {
        return this.monthNumber;
    }

    public int CompareTo(Month other)
    {
        if (other == null)
        {
            throw new ArgumentNullException("other");
        }

        return this.monthNumber - other.monthNumber;
    }

    public static bool operator ==(Month left, Month right)
    {
        return left != null && left.Equals(right);
    }

    public static bool operator !=(Month left, Month right)
    {
        return !(left == right);
    }

    public static implicit operator int(Month month)
    {
        return month.MonthNumber;
    }

    public static Month operator +(Month month, int months)
    {
        return new Month(month.MonthNumber + months);
    }

    public static Month operator -(Month month, int months)
    {
        return new Month(month.MonthNumber - months);
    }

    public override string ToString()
    {
        return this.monthNumber.ToString("00");
    }

    public override object ConvertTo(Type destinationType)
    {
        if (destinationType == typeof(int))
        {
            return this.MonthNumber;
        }

        throw new NotSupportedException();
    }

    public string ToString(IFormatProvider formatProvider)
    {
        return this.ToString();
    }
}

Draft3

using System;

public struct Month : IEquatable<Month>, IComparable<Month>, IConvertible, IFormattable
{
    public static readonly Month January = new Month(1);
    public static readonly Month February = new Month(2);
    public static readonly Month March = new Month(3);
    public static readonly Month April = new Month(4);
    public static readonly Month May = new Month(5);
    public static readonly Month June = new Month(6);
    public static readonly Month July = new Month(7);
    public static readonly Month August = new Month(8);
    public static readonly Month September = new Month(9);
    public static readonly Month October = new Month(10);
    public static readonly Month November = new Month(11);
    public static readonly Month December = new Month(12);

    private readonly int monthNumber;

    public Month(int monthNumber)
    {
        if (monthNumber < 1 || monthNumber > 12)
        {
            throw new ArgumentOutOfRangeException("monthNumber");
        }

        this.monthNumber = monthNumber;
    }

    public int MonthNumber
    {
        get { return this.monthNumber; }
    }

    public static IEnumerable<Month> Values
    {
        get
        {
            yield return January;
            yield return February;
            yield return March;
            yield return April;
            yield return May;
            yield return June;
            yield return July;
            yield return August;
            yield return September;
            yield return October;
            yield return November;
            yield return December;
        }
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
        {
            return false;
        }

        if (obj is Month)
        {
            return this.Equals((Month)obj);
        }

        return false;
    }

    public bool Equals(Month other)
    {
        return this.MonthNumber == other.MonthNumber;
    }

    public override int GetHashCode()
    {
        return this.MonthNumber;
    }

    public int CompareTo(Month other)
    {
        return this.MonthNumber - other.MonthNumber;
    }

    public static implicit operator int(Month month)
    {
        return month.MonthNumber;
    }

    public static implicit operator Month(int monthNumber)
    {
        return new Month(monthNumber);
    }

    public override string ToString()
    {
        return this.MonthNumber.ToString("00");
    }

    public string ToString(IFormatProvider formatProvider)
    {
        return this.ToString();
    }
}

3つともちゃんと構造体(struct)になっています。いいですね。
Draft1 ではインターフェイスが一つも実装されていません。Draft2、Draft3ではインターフェイスは実装されていますが、ICompatible インターフェイスがないですね。指示が明確でなかったか、IComparable と IComparable<Month> の違いが理解できなかったか…
また、IEnumerable<Month> も構造体自体には実装せず、Drawft3では代わりにValuesプロパティで実装していますね。
ラムダ式などは使われませんでした。

Bing

BIngはコーディングしてくれませんでした(たまたまの可能性はあるけど)。
以下がBingの回答

. I can help you Hello, this is Bing with coding structures in C#.😊

A structure type (or struct type) is a value type that can encapsulate data and related functionality. You use the struct keyword to define a structure type1. For example:

public struct Coords
{
    public Coords(double x, double y)
    {
        X = x;
        Y = y;
    }

    public double X { get; }
    public double Y { get; }

    public override string ToString() => $"({X}, {Y})";
}

To implement interfaces, you need to use the colon (:) operator after the struct name and list the interfaces separated by commas2. For example:

public struct Month : IEnumerable<Month>, IEquatable<Month>, IComparable, IComparable<Month>, IConvertible, IFormattable
{
    // struct body
}

To implement methods, you need to use the public keyword and specify the return type and the parameters of the method. You can also use expression-bodied methods to write concise code1. For example:

public Month Add(int months)
{
    // method body
}

// or

public Month Add(int months) => // expression body;

To allow implicit cast to int type, you need to use the implicit keyword and define a conversion operator that takes a Month parameter and returns an int value2. For example:

public static implicit operator int(Month m) => // conversion logic;

To allow comparison operators, you need to use the public static keywords and define the operators using the symbols <, >, <=, >=, ==, !=2. For example:

public static bool operator <(Month m1, Month m2) => // comparison logic;
public static bool operator >(Month m1, Month m2) => // comparison logic;
// and so on

I hope this helps you get started with coding structures in C#. Do you have any questions?

…自分で作れということらしいです。

Hugging Chat

public class Month : EnumerableEx<Month>, IEquatable<Month>, IComparable<Month>, IComparable<int>, IConvertible, IFormattable
{
    public static readonly Month January = new Month(1);
    public static readonly Month February = new Month(2);
    public static readonly Month March = new Month(3);
    public static readonly Month April = new Month(4);
    public static readonly Month May = new Month(5);
    public static readonly Month June = new Month(6);
    public static readonly Month July = new Month(7);
    public static readonly Month August = new Month(8);
    public static readonly Month September = new Month(9);
    public static readonly Month October = new Month(10);
    public static readonly Month November = new Month(11);
    public static readonly Month December = new Month(12);
    
    private int _value;
    
    public Month(int value)
    {
        _value = value;
    }
    
    public static Month FromValue(int value) => new Month(value);
    
    public override string ToString() => $"MMM yyyy"; // TODO: Format this better
    
    public int GetHashCode() => _value.GetHashCode();
    
    public bool Equals(object obj) => Equals((Month)obj);
    
    public void CopyTo(Month[] array, int index) => (array ??= new Month[0]).CopyTo(new Month[index], index, Length);
    
    public IEnumerator<Month> GetEnumerator() => this;
    
    IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator();
    
    protected bool TryFormatTo(Formatter formatter, out object result)
    {
        if (!formatter.HasStandardValuesSupport())
            return false;
        
        var value = Value;
        result = (int)Value?.ToString("D2");
        return true;
    }
    
    public static explicit operator Month(int value) => new Month(value);
    publ

途中で止まってしまいました。続けて書くように指示しても、全然関係のないコーディングを始めてしまったので、あきらめました。ChatGPTでは続きを書くように指示するとちゃんと続きを書いてくれたのですが…
これもChatGPT同様、構造体ではなくクラスになっていますね。IEnumerable<Month>ではなく、EnumerableExになっています。
でも、ラムダ式で書けるところはラムダ式で書いています。初期化での型名省略はしていないですが。

番外編:(Stable Diffusion 1.5)

完全にお遊びですが、このプロンプトを画像生成AIに流すとどうなるんだろうか?と…
で、出来上がった画像がこちら

1枚目
2枚目
3枚目
4枚目

2枚目は結構コーディングっぽい。
他はコーディングってより仕様書っぽいかなぁ(笑)

さいごに

検証目的であれば、様々なプロンプトを試したり、何度も出力させたりするのでしょうが、今回はお遊びなのでこんな感じで良いかなと思っています。
ま、それぞれの特徴を知って、うまく活用することにします。


いいなと思ったら応援しよう!

この記事が参加している募集