November 24, 2022

On Monday, 7 November 2022 at 09:07:48 UTC, Ali Çehreli wrote:

>

Phobos'tan kopya çekilebilir herhalde.

Hiç de kopyaya ihtiyacımız yok hocam, çünkü birkaç deneme yanılma ile 48 saatte çözdüm olayı 😀

Aşağıdaki henüz test kodu, bir nevi preview dediğimiz cinsten ve itiraz yoksa v3'e release olacak inşaallah çünkü...

Bu InclusiveRange çözümü için çift şablon/yapı/işlev kullandım. Aslında şablonların biri olan Value, mixin template ve front kısmından sorumlu. Adımlama (step veya s) ise derleme zamanında belirleniyor. Tabi hoşuna gitmeyen bunu işlev parametresine de taşıyabilir. Sanırım tüm testlerden başarı ile geçiyor ve evet bütün parametreler kullanınca tür çıkarsaması zayıf.

Özetle geliştirilebilir ama Phobos'daki iota'dan daha kısa ve çok daha üstün!

auto inclusiveRange(T)(T oneValue) {
  return inclusiveRange!T(T(0), oneValue);
}

template inclusiveRange(Type, Type s = 1) {
  static if(is(Type == bool)) {
    static assert(0, "\nBoolean type cannot be used!");
  }

  auto inclusiveRange(Type f, Type l) {
    return InclusiveRange(f, l);
  }

  struct InclusiveRange {
    mixin Value!Type;
    Type l, term;

    this(Type first, Type last)
    {
      f = Value(first);  /*****************************************/
      l = term = last;
      if(diff % s) {
        const t = cast(Type)(diff / s);
        term = cast(Type)(t * s + first);
      }
    }

    private auto diff() { return term - front; }

    bool empty() { return f.empty || front > l; }
    Type front() { return f.value; }
    auto popFront() { f += s; }

    auto length() {
      return empty ? 0 :
             cast(size_t)(diff / s) + 1;
    }
  }
}

template Value(Type) {
  Value f;
  struct Value
  {
    Type value;
    bool empty;

    auto ref opAssign(Type first)
    {
      return value = first;
    }

    auto ref opOpAssign(string op)(Type first)
    if(op == "+")
    {
      const prev = value;
      value += first;
      if(value < prev)
      {
        empty = true;
        value = prev;
      }
    }
  }
} unittest {
  alias TT = uint; // TestType
  Value!TT test;
  test = TT.max;
  test += 1;
  assert(test.empty);
  assert(test.value == TT.max);

  test = TT.min;
  test -= 1;
  assert(test.empty);
  assert(test.value == TT.min);
}

alias ir = inclusiveRange;
alias iras = inclusiveRange;

auto Tester(E, T)(bool printOut = false) {
  size_t counter;
  T t = E.f;

  with(E) {
    while(t <= l) {
      counter++;
      t += s;
    }
    auto test = ir!(T, s)(f, l);
    if(printOut) {
      import std.stdio : write, writeln;
      test.write(": ");
      counter.writeln;
    }
    import std.algorithm : count;
    assert(test.count == counter);
    assert(test.length == counter);
  }
  return counter;
}

Bol örneklerin olduğu test koduna ihtiyaç duyarsanız aşağıdaki gibi bir sonuç alınıyor:

>

AFKPUZ: 6
ABCDEFGHIJKLMNOPQRSTUVWXYZ
[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4]
[0, 0.1, 0.2, 0.3, 0.4, 0.5]
[0, 0.1, 0.2, 0.3, 0.4, 0.5]
[0, 0.1, 0.2, 0.3, 0.4, 0.5]
[0, 0.1, 0.2, 0.3, 0.4]

void main()
{
  import std.range;

  alias T1 = double;  /*****************************************/
  enum irrationalTest : T1 {
    f = 0.1, l = 2.09,
    s = 0.11
  } // x19 elements
  //assert(Tester!(irrationalTest, T1) == 19);
  /*****************************************
   Nedense Tester() içindeki test.count 18
   sayıyor! Eski sürümlerde daha iyi çalışır!
   Aynı sürümde aralığı ekrana yazdırdığınızda
   19 elemanlı olduğu çok net. Belli ki sorun
   başka şeyle ilgili o yüzden iptal...
   *****************************************/

  alias T2 = uint;
  enum integerTest {
    f = 2022, l = 10110,
    s = f
  } // x5 elements
  assert(Tester!(integerTest, T2) == 5);

  /*****************************************/

  alias T3 = char;
  enum asciiCharTest {
    f = 65, l = 90,
    s = 5
  } // x6 elements [AFKPUZ]]
  assert(Tester!(asciiCharTest, T3)(true) == 6);

  /*****************************************/

  alias T4 = ubyte;
  auto fullRange = ir(T4.min, T4.max);
  assert(fullRange.length == T4.max + 1);
  static assert(is(
    ElementType!(typeof(fullRange)) == T4)
  );

  /*****************************************/
  /* Odd/Even testing:
  auto o = ir!(ushort, 2)(1, 100);
  foreach(number; o)  /*****************************************/  /*****************************************/  /*****************************************/
  {
    assert(isOdd(number));
  }

  o = ir!(ushort, 2)(2, 100);
  foreach(number; o)
  {
    assert(isEven(number));
  }
  //*/
  /*****************************************/
  import std.stdio;

  ir('A', 'Z').writeln;
  iota('A', 'Z').writeln; // different results  /*****************************************/

  auto zeroTest = ir!(float, 5)(-5, 5).array;
  assert(zeroTest[0] + zeroTest[2] == zeroTest[1]);

  ir(5).writeln;
  auto i1 = iota(5);
  writeln(i1) ;// different results

  ir!(double, .1)(0, .51).writeln;
  auto i2a = iota!double(0, .51, .1);
  writeln(i2a); // ** same results **

  ir!(double, .1)(0,.5).writeln;
  auto i2b = iota!double(0, .5, .1);
  writeln(i2b); // different results

  //auto True = iras(true); // assert error
  //auto False = iras(false, true); // assert error

  assert(ir(0).array == [0]);
  assert(ir(0, 0).array == [0]);
  assert(ir(0, 1).array == [0, 1]);
  assert(ir(-1, 0).array == [-1, 0]);

      assert(ir(-1).array == []);
     assert(iota(0).array == []);  /*****************************************/
    assert(iota(-1).array == []);
  assert(iota(0, 0).array == []);

  assert(iota(0, 1).array == [0]);
  assert(iota(-1, 0).array == [-1]);
}

Başarılar...

1 2 3
Next ›   Last »