Thread overview
Index kullanmadan kosullu birşekilde aralıklarla altküme sayısını bulma
Mar 16, 2018
kerdemdemir
Mar 18, 2018
kerdemdemir
Mar 20, 2018
kerdemdemir
March 16, 2018

Diyelimki elimde iki dizi var :

2 5 3 1 11 4 4
7 8 2 4 1 8

Şöyle toplamı eşit alt kümeler oluşturmaya çalışıyorum.

[2,5] = [7] = 7
[3 1 11] = [8 2 4 1] = 15
[4 4] = [8] = 8

Yani eşit oluncaya kadar ilerlemek istiyorum.

Ben bunu şöyle index kullanarak çözdüm :


import std.stdio;
import std.algorithm;
import std.range;
import std.string;
import std.array;
import std.conv;
import std.math;


void Isle(T)( T küçükDizi, T büyükDizi, ref int kacKere )
{
	int hedef = büyükDizi.front();
	büyükDizi.popFront();
	int toplam = 0;
	while( true )
	{
		toplam += küçükDizi.front();
		if (toplam <= hedef )
			küçükDizi.popFront();

		if ( toplam >= hedef )
		{
			if ( küçükDizi.empty() || büyükDizi.empty() )
			{
				kacKere++;
				return;
			}
			else
			{
				if ( toplam > hedef)
					küçükDizi.front() = toplam - hedef;
				else
					kacKere++;

				if( küçükDizi.front > büyükDizi.front )
					Isle(büyükDizi, küçükDizi, kacKere);
				else
					Isle(küçükDizi, büyükDizi, kacKere);
			}
			return;
		}
	}
}


int main(string[] argv)
{
	auto girişDizisi = stdin.readln.to!dstring.chomp.split.map!( a => to!int(a) );
	auto ilkDizi = stdin.readln.to!dstring.chomp.split.map!( a => to!int(a) ).array;
	auto ikinciDizi = stdin.readln.to!dstring.chomp.split.map!( a => to!int(a) ).array;
	int sonuç = 0;
	if( ilkDizi.front > ikinciDizi.front )
		Isle(ikinciDizi, ilkDizi, sonuç);
	else
		Isle(ilkDizi, ikinciDizi, sonuç);
	writeln(sonuç);
   return 0;
}

Sorunun aslı şu linkte http://codeforces.com/contest/950/problem/B

Walter abimizin özlü sözü "programramımızdaki döngüler buglardır" deyişinden dolayı Işle metodundan "while(true)" 'u çıkarmak istiyorum .

Öyle bir method lazımki bir şekilde toplamı alarak ilerliyecek o nokta geldiğinde bana o aralığın sonrasını verecek.
Acaba böyle bir std methodu varmıdır ?

Erdemdem

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 19, 2018

Tam ihtiyacim olan sey. Uygulamali bir aralik ornegi. Eve gidince veya ogle arasinda etud edicem . Cok tesekkur ederim.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 18, 2018

Döngü olmasa daha iyi olduğu doğru ama zorlamamak gerek. :) Hele döngüyü sonlandıran birden fazla koşul varsa 'while(true)' gibi döngüler çok uygundur. (Hatta bunu Andrei'nin kendisinden duymuştum.)

Belki Phobos olanaklarıyla daha temiz yapılabilir. Ben normal döngüler kullanarak ama aralık çokuzlusu döndüren bir aralık olarak yazmak istedim. Bütün ForwardRange türleriyle çalışabiliyor olması lazım ama yalnızca senin verdiğin iki dilimle denedim:

import std.stdio;
import std.range;

struct EşitToplamlı(A, B) {
   A a;
   B b;

   // Kaçar elemanın front'a dahil olduğu:
   size_t aAdet;
   size_t bAdet;

   // 'aralık'ı ilerleterek toplamları eşit yapmaya çalışır; kaç adet ilerlettiğini döndürür
   size_t ilerlet(X, E, Y)(ref X aralık, ref E buToplam, Y diğerToplam) {
       size_t adet = 0;
       while (buToplam < diğerToplam) {
           buToplam += aralık.front;
           aralık.popFront();
           ++adet;

           if (aralık.empty) {
               break;
           }
       }
       return adet;
   }

   // front elemanı hazırlar
   // (Bu işlev bazı kütüphanelerde prime() adıyla geçiyor)
   void hazırla() {
       if (this.empty) {
           return;
       }

       // İlerletilecek geçici aralıklar
       auto a2 = a.save();
       auto b2 = b.save();

       // İlk elemanlarla başlıyoruz
       auto aToplam = a2.front;
       auto bToplam = b2.front;
       a2.popFront();
       b2.popFront();
       aAdet = 1;
       bAdet = 1;

       while (true) {
           if (aToplam == bToplam) {
               break;
           }

           if (a2.empty) {
               a = a2; // Böylece empty==true olacağız
               break;
           }

           if (b2.empty) {
               b = b2; // Böylece empty==true olacağız
               break;
           }

           if (aToplam < bToplam) {
               aAdet += ilerlet(a2, aToplam, bToplam);
           }

           if (bToplam < aToplam) {
               bAdet += ilerlet(b2, bToplam, aToplam);
           }
       }
   }

   this(A a, B b) {
       this.a = a;
       this.b = b;
       hazırla();
   }

   bool empty() {
       return a.empty() || b.empty();
   }

   // Aralıkların kaldıkları yerden başlayan uygun sayıda elemanı iki aralıktan oluşan çokuzlu olarak döndürür.
   auto front() {
       import std.typecons;
       return tuple(a.take(aAdet), b.take(bAdet));
   }

   void popFront() {
       a.popFrontN(aAdet);
       b.popFrontN(bAdet);
       aAdet = 0;
       bAdet = 0;
       hazırla();
   }
}

auto eşitToplamlı(A, B)(A a, B b) {
   return EşitToplamlı!(A, B)(a, b);
}

void main() {
   auto a = [2, 5, 3, 1, 11, 4, 4, 42];
   auto b = [7, 8, 2, 4, 1, 8, 43];
   writefln("%(%s\n%)", eşitToplamlı(a, b));
}

Sona kalan elemanların kullanılmayacaklarını varsaydım. Kendim eklediğim 42 ve 43 çıktıda belirmiyorlar:
'
Tuple!(int[], int[])([2, 5], [7])
Tuple!(int[], int[])([3, 1, 11], [8, 2, 4, 1])
Tuple!(int[], int[])([4, 4], [8])
'
Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 21, 2018

Tamamen anladim .

   auto a2 = a.save();

Methodunu ilk defa goruyorum. Kopyalama yapiyormu yapmiyormu cozemedim. Bence yapiyordur cunku "aralık.popFront();" "a" 'yida etkilerdi. Ama karanlik isler donuyor olabilir tabi.

Erdemdem

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 21, 2018

Hayır, save eleman kopyalamıyor; yalnızca aralık kavramı kopyalanıyor. (Dilimlerde yalnızca gösterge ve uzunluğun kopyalanması gibi.)

front, empty, ve popFront InputRange yapıyor; save'i ekleyince ForwardRange haline geliyor. Aralıkta ilerledikçe elemanların kendilerini tüketmeyen her topluluk tarafından sunulabilir:

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]