May 09, 2022

On Monday, 9 May 2022 at 03:25:26 UTC, Salih Dincer wrote:

>

Bu da bilinçli değinmedim sorun. Malum türlerin sınırı olduğu için ve Inclusive Range hepsini kapsamaya çalıştığından patlıyor.

Özetle, bu kadarı kadı kızında da olur diyorum ve bu iki durum ile yaşayabilirim. :)

Düzeltiyorum: Yaşayamayız...

Çünkü sonsuz döngü kabul edilemez! İşe gelmek için yolda yürüyorken biraz düşündüm ve az önce mola arasında uyguladım. Aslında çözüm çok basitmiş. Sadece 2. bir bool Empty ve önceki değeri sorgulama mekanizması, kontrolü bir üst seviyeye çıkarıyor:

struct InclusiveRange(T) {
  T front, last, step, term;
  bool Empty;

//...

  bool empty()
  {
    if(Empty) {
      Empty = false;
      return true;
    } else return front > last;
  }

  void popFront()
  {
    const prev = front;
    front += step;
    if(front < prev) Empty = true;
  }
}

unittest
{
  assert(inclusiveRange!byte(0, 127).last == byte.max);
  assert(inclusiveRange!ubyte(0, 255).last == ubyte.max);
  assert(inclusiveRange!int(0, 2147483647).last == int.max);
  assert(inclusiveRange!uint(0, 4294967295).last == uint.max);
}

Pahalı bir çözüm mü?

May 09, 2022

On Monday, 9 May 2022 at 07:29:52 UTC, Salih Dincer wrote:

>

Pahalı bir çözüm mü?

Çözümü kanıtlamak için acele etmişim! Bir diziye çevirip aralığı işletmediğim için düzeltmem gerekiyor...

Sanırım aşağıdakiler, temel türler için istediğim (son 2 elemanın dizisini üreten) test oldu. Bundan sonra temel türlere ve char/string gibi izin vermeyen sözleşmeli programlama kısmını yapmak gerekiyor.

unittest
{
  assert(inclusiveRange!byte(byte.max-1, byte.max).array.length == 2);
  // [126, 127]
  assert(inclusiveRange!ubyte(ubyte.max-1, ubyte.max).array.length == 2);
  // [254, 255]
  assert(inclusiveRange!short(short.max-1, short.max).array.length == 2);
  // [32766, 32767]
  assert(inclusiveRange!ushort(ushort.max-1, ushort.max).array.length == 2);
  // [65534, 65535]
  assert(inclusiveRange!int(int.max-1, int.max).array.length == 2);
  // [2147483646, 2147483647]
  assert(inclusiveRange!uint(uint.max-1, uint.max).array.length == 2);
  // [4294967294, 4294967295]
  assert(inclusiveRange!long(long.max-1, long.max).array.length == 2);
  // [9223372036854775806, 9223372036854775807]
  assert(inclusiveRange!ulong(ulong.max-1, ulong.max).array.length == 2);
  // [18446744073709551614, 18446744073709551615]
}

import std.stdio;
import std.range;

void main()
{
  iota!byte(byte.max-1, byte.max).array.writeln;
  iota!ubyte(ubyte.max-1, ubyte.max).array.writeln;
  iota!short(short.max-1, short.max).array.writeln;
  iota!ushort(ushort.max-1, ushort.max).array.writeln;
  iota!int(int.max-1, int.max).array.writeln;
  iota!uint(uint.max-1, uint.max).array.writeln;
  iota!long(long.max-1, long.max).array.writeln;
  iota!ulong(ulong.max-1, ulong.max).array.writeln;
}

iota() çıktısı ve zayıf kaldı durumu ise gözler önünde:

>

[126]
[254]
[32766]
[65534]
[2147483646]
[4294967294]
[9223372036854775806]
[18446744073709551614]

Yani sınırları aralık olarak veremiyor. Özetle artık inclusiveRange(), eski klasik çözüme göre üstün konumda!

Başarılar...

May 29, 2022

Merhaba,

iota şunu yapıyor ama bizim yapı yarı yolda kalıyor:

  iota(-5, 0).writeln; // [-5, -4, -3, -2, -1]
  ir(-5, 0).writeln; // []

Bunun çözümünü henüz bilmiyorum ama v2.1.0 ile sorunsuz çalışıyor, bildirmek istedim. Çözene kadar da iota'nın yerini alamayacağını düşünüyorum. Tek sorun o kaldı :)

Bunun dışında ilk defa enumerate() ile denedim, çalışıyor:

void main()
{
  enum start = 11, end = 20;
  auto range = start.inclusiveRange(end);

  foreach(index, test; range.enumerate(start))
  {
    writeln(index, ": ", test);
    assert(index == test);
  }
}

Malum, aralıklar dizilerde olduğu gibi bir index değeri sunamıyor. Çalışıp çalışmadığını merak etmiştim.

Bu arada yeni D sürümünden memnun olmayanlar var, bakalım Haziran'da n'olcak :)

Sevgiler, saygılar...

November 05, 2022

On Sunday, 29 May 2022 at 19:11:51 UTC, Salih Dincer wrote:

>

iota şunu yapıyor ama bizim yapı yarı yolda kalıyor:

  iota(-5, 0).writeln; // [-5, -4, -3, -2, -1]
  ir(-5, 0).writeln; // []

Buna çözüm bulamadım :(

alias ir = inclusiveRange;
alias iras = inclusiveRange;

auto inclusiveRange(T)(T Args...) if(is(T == bool))
  => assert(0, "\nBoolean type cannot be used!");

auto inclusiveRange(T = int)(T f = T(0), T l = T(0), T s = T(1))
  => l > T(0) ? InclusiveRange!T(f, l, s): InclusiveRange!T(T(0), f, s);/*
  => InclusiveRange!T(f, l, s);//*/

struct InclusiveRange(T) {
   T front, last, step, term;
   bool Empty;

  this(T front, T last, T step) {
    this.front = front;
    this.last = last;
    this.step = step;
    this.term = last;
    if(this.diff % step) {
      const t = cast(int)(this.diff / step);
      this.term = cast(T)(t * step + this.front);
    }
  }

  T sum() {
    const residueCheck = front ? 2 * front + diff : diff;
    return cast(T)(length * residueCheck / 2);
  }

  bool empty() {
		if(Empty) {
      Empty = false;
      return true;
    } else return front > last;
  }

  void popFront() {
    const prev = front;
    front += step;
    if(front < prev) Empty = true;
  }

  auto opSlice(T a, T b)
  in (b<=this.length) =>
    InclusiveRange!T(cast(T)(front + a * step),
        cast(T)(front + (b - 1) * step), step);

  auto opSlice() => this;
  auto opDollar() => this.length;

  T back() => last;
  auto popBack() => !empty ? last -= step : step;

  auto diff() => term - front;
  auto length() => cast(int)(diff / step + 1);

  auto save() => this;
}

Sevgiler, saygılar...

November 05, 2022
On 11/5/22 09:38, Salih Dincer wrote:
> On Sunday, 29 May 2022 at 19:11:51 UTC, Salih Dincer wrote:
>> iota şunu yapıyor ama bizim yapı yarı yolda kalıyor:
>> ```d
>>   iota(-5, 0).writeln; // [-5, -4, -3, -2, -1]
>>   ir(-5, 0).writeln; // []
>> ```
>
> Buna çözüm bulamadım :(

empty() ilk baştan 'true' mu oluyor acaba?

>    bool empty() {
>          if(Empty) {
>        Empty = false;
>        return true;
>      } else return front > last;
>    }

Art arda çağrıldığında empty()'nin aynı değeri döndürmesi beklenir. (Böyle işlemlere "idempotent" denir.)

empty()'nin bu nesnede değişiklik yapıyor olması hemen dikkat çekiyor. Bütün değişiklik popFront()'ta yapılmalı, değil mi?

Kodun başka tarafına bakmadım çünkü yukarıdaki oldukça sağlam bir gözlem.

Ali

November 06, 2022

On Saturday, 5 November 2022 at 19:18:50 UTC, Ali Çehreli wrote:

> >
   bool empty() {
         if(Empty) {
       Empty = false;
       return true;
     } else return front > last;
   }

Art arda çağrıldığında empty()'nin aynı değeri döndürmesi beklenir. (Böyle işlemlere "idempotent" denir.)

empty()'nin bu nesnede değişiklik yapıyor olması hemen dikkat çekiyor. Bütün değişiklik popFront()'ta yapılmalı, değil mi?

Bir sorunu (taşma yapıp sonsuz döngüye girmesini) düzeltmek için 2. bir Empty özelliğine ihtiyaç duydum ve tabii farkında olmadan başka bir soruna kucak açtığım bariz şekilde belli.

Belli olmayan entropi! Yani biz neticede kapalı (isolated) bir sistem içinde bir iş yapıyoruz ve bunu düzenli olması için çabalıyoruz. Ama düzensiz bu evrende bunun bedeli başka bir sorun olarak dönüyor. Bunu lisede, termodinamiğin 2. kanunda okumuştuk.

Özetle şuraya kadar, yazı yerine 2 satır kod yazıp çözdüm demek isterdim ama olmuyor. Buradan, programcılık dünyasında neden sınırların limit-1'de bitip index = 0'dan başladığı ortaya çıkıyor.

Teşekkürler...

November 06, 2022
On 11/6/22 14:46, Salih Dincer wrote:

> olmuyor.

Aşağıdaki çok mu basit? Belki de "basit ise doğrudur" diye düşünmeliyiz. :)

import std.stdio;
import std.range;

struct InclusiveRange(T) {
    T baş;
    T son;
    T adım;
    bool empty;

    this(T baş, T son, T adım) {
        this.baş = baş;
        this.son = son;    // Bunu biraz sonra düzelteceğiz
        this.adım = adım;

        // InputRange ve BidirectionalRange değerlerimiz aynı olsun diye
        // 'son'u değiştiriyoruz. (Buradaki 'length', eski olan 'son'
        // değerini kullanıyor.)
        import std.conv : to;
        this.son = ((length - 1) * adım).to!T;
    }

    auto length() {
        return empty ? 0 : size_t((son - baş) / adım) + 1;
    }

    T front() {
        return baş;
    }

    void popFront() {
        if (baş == son) {
            empty = true;

        } else {
            baş += adım;
        }
    }

    auto save() {
        return this;
    }

    T back() {
        return son;
    }

    void popBack() {
        if (son == baş) {
            empty = true;

        } else {
            son -= adım;
        }
    }
}

auto inclusiveRange(T)(T baş, T son, T adım) {
    return InclusiveRange!T(baş, son, adım);
}

void main() {
    auto r = inclusiveRange(ubyte.min, ubyte.max, 7);
    writeln(r);
    writeln(r.retro);
}

Ali

November 06, 2022
On 11/6/22 15:34, Ali Çehreli wrote:

>          this.son = ((length - 1) * adım).to!T;

Doğrusu:

        this.son = baş + ((length - 1) * adım).to!T;

Ali

November 07, 2022

On Sunday, 6 November 2022 at 23:34:44 UTC, Ali Çehreli wrote:

>
import std.stdio;
import std.range;

struct InclusiveRange(T) {
    T baş;
    T son;
    T adım;
    bool empty;

    this(T baş, T son, T adım) {
        this.baş = baş;
        this.son = son;    // Bunu biraz sonra düzelteceğiz
        this.adım = adım;

        // InputRange ve BidirectionalRange değerlerimiz aynı olsun diye
        // 'son'u değiştiriyoruz. (Buradaki 'length', eski olan 'son'
        // değerini kullanıyor.)
        import std.conv : to;
        this.son = ((length - 1) * adım).to!T;
    }

    auto length() {
        return empty ? 0 : size_t((son - baş) / adım) + 1;
    }

    T front() {
        return baş;
    }

    void popFront() {
        if (baş == son) {
            empty = true;

        } else {
            baş += adım;
        }
    }

    auto save() {
        return this;
    }

    T back() {
        return son;
    }

    void popBack() {
        if (son == baş) {
            empty = true;

        } else {
            son -= adım;
        }
    }
}

auto inclusiveRange(T)(T baş, T son, T adım) {
    return InclusiveRange!T(baş, son, adım);
}

Hocam maalesef bir tarafını düzeltince başka tarafı patlıyor. Şimdi patladığı yer ise ondalıklı sayılar. Gerçi length() çalışmadığı için ekleme yapmam gerekti. Kısmen çalışsa da gizlenen r2 örneğinde sonsuz döngüye giriyor. Önceki sürümde bu testi geçiyordu. Şu sonuçları almak gerekiyor:

>

[0.1, 0.21, 0.32, 0.43, 0.54, 0.65, 0.76, 0.87, 0.98, 1.09, 1.2, 1.31, 1.42, 1.53, 1.64, 1.75, 1.86, 1.97, 2.08]

En azından 4. bir terim (son'un ilk hali) ekleme gerekiyordu:

struct InclusiveRange(T) {
    T baş, son, adım;
    T term;  // SDB ekledi
    bool empty;

    this(T baş, T son, T adım) {
        this.baş = baş;
        this.adım = adım;
        this.term = son; // SDB ekledi

        import std.conv : to;
        this.son = baş + ((length - 1) * adım).to!T;/* Ali
        this.son = ((length - 1) * adım).to!T;//*    düzelti*/
    }

    auto length() {
        return empty ? 0 : cast(size_t)((term - baş) / adım) + 1;/* SDB
        return empty ? 0 : size_t((son - baş) / adım) + 1;//*     ekledi*/
    }
//...

Test için ise şunları denedim (gizlenen açılırsa patlıyor):

void main() {
    auto r = inclusiveRange(ubyte.min, ubyte.max, 7);
    writeln(r);

    auto r2 = inclusiveRange(0, 1.5, 0.1);/*
    auto r2 = inclusiveRange(0.1, 2.09, 0.11);//*/
    writeln(r2);

    auto x = 2022;
    auto r3 = inclusiveRange(x, 10110, x);
    assert(r3.length == 5); // tam sayılar testi tamam
}

Başarılar...

November 07, 2022
On 11/6/22 21:54, Salih Dincer wrote:

> ondalıklı sayılar

Çok hızlıca yazdım ama ondalıklı sayıların özel ilgi istediğini hatırlamalıydım:

  https://youtu.be/gwUcngTmKhg?t=702

Phobos'tan kopya çekilebilir herhalde.

Ali