Memilih pengaturan makanan yang paling berkalori-rata

9

Misalkan saya makan lima kali sehari, dan karena ada tujuh hari dalam seminggu, saya punya resep untuk tujuh kali makan, total 35 resep. Setiap resep memiliki jumlah kalori. Setiap hari harus mengandung satu resep per makanan, dan setiap resep ditetapkan untuk makanan tertentu (misalnya Anda tidak bisa makan pancake untuk makan malam). Semua 35 resep harus ada dalam solusi, sehingga resep tidak dapat diulang selama seminggu.

Saya ingin menemukan pengaturan makanan yang akan memberikan jumlah kalori paling rata per hari - yaitu, saya ingin meminimalkan perbedaan total kalori yang dikonsumsi dari hari ke hari.

Ini bukan masalah pekerjaan rumah - itu sebenarnya benar! Saya tidak bisa datang dengan pendekatan yang lebih baik daripada brute-force, dan ada 7! ^ 4 kombinasi, yang banyak.

dfaulken
sumber
3
Saya punya firasat bahwa ini adalah variasi dari masalah stok pemotongan atau mungkin masalah pengepakan bin .
Doval
Untuk memperjelas - Anda memiliki 7 resep untuk "makanan pertama hari itu", 7 untuk "makanan kedua", 7 untuk "makanan ketiga", dan seterusnya? Apakah Anda pernah menetapkan resep "makanan pertama" untuk "makanan terakhir hari ini"? (Dengan kata lain, maukah Anda menyajikan pancake untuk makan malam?)
Dan Pichelman
Benar; kamu tidak akan.
dfaulken
2
Apakah semua 35 resep memiliki jumlah kalori yang sangat berbeda ? Jika Anda membulatkan jumlah kalori hingga 10 atau 50 kalori terdekat, 7! ^ 4 mungkin dengan mudah menjadi 3! ^ 4 - yang mudah dihitung melalui kekuatan kasar
Dan Pichelman
2
Bung, Anda makan terlalu banyak, makan 5 kali / hari akan membuat Anda kelebihan berat badan.
Pieter B

Jawaban:

1

Untuk membuat pendekatan yang lebih formal untuk masalah Anda:

Anda memiliki masing-masing 5 daftar 7 angka. Anda perlu membuat 7 daftar yang masing-masing terdiri dari 5 angka, dan menemukan solusi yang memiliki perbedaan minimal antara daftar yang memiliki jumlah angka terbesar dan satu dengan yang terkecil.

Jika Anda ingin menemukan solusi optimal tanpa heuristik, saya yakin Anda tidak punya banyak pilihan selain untuk menghitung, tetapi Anda tidak perlu menyebutkan semuanya.

Apa pun solusi yang Anda temukan, ketika Anda mendaftarkannya sebagai "yang terbaik ditemukan sejauh ini", daftarkan kinerjanya mengenai metrik Anda (saya percaya itu adalah perbedaan minimal). Kemudian, jika cabang solusi jelas keluar dari jalan ini, berhentilah menghitungnya. Protip: hari-hari non-bangun akan memiliki jumlah kalori terbaik yang merupakan rata-rata dari semua makanan yang tersisa. Jadi, bayangkan Anda memiliki daftar yang [10, 2, 2, 1, 1, 0, 0]untuk semua 5 makanan, dan Anda membangun solusi 10 di setiap makan untuk hari 1. Anda tahu hari-hari yang tersisa akan rata-rata 5 kalori per hari, jadi perbedaannya akan setidaknya 45 dan jadi jika Anda sebelumnya menemukan solusi, katakanlah max - min = 10, Anda tidak perlu melangkah lebih jauh. Anda akan langsung mencoba menu lain untuk hari 1.

Arthur Havlicek
sumber
Ini bukan masalah tempat sampah. Masalah tempat sampah bukanlah jumlah tempat sampah yang tetap dan jumlah barang yang tidak diperbaiki per tempat sampah.
paparazzo
Ya kamu benar. Saya benar itu.
Arthur Havlicek
0

Ini hanya retasan tetapi akan membuat Anda tutup
Hanya 3 kali makan
Pada dasarnya Anda gagal makan jika itu membuat dua hari lebih dekat dengan rata-rata C #

Pendekatan yang lebih baik adalah mengembalikan boolen pada Flop dan beralih kembali sampai selesai.

Flop bisa menjadi lebih pintar. Anda mungkin berada dalam posisi tidak gagal sarapan untuk gagal makan siang dan makan malam. Mungkin ada permutasi kode yang sulit. Ini lebih seperti semacam nilai gagal daripada menyortir.

public static void MealEven()
{
    List<Day> Days = new List<Day>();
    Random rnd = new Random();
    decimal sum = 0;
    for(int i = 0; i<7; i ++)
    {
        int b = rnd.Next(100) + 40;
        int l = rnd.Next(100) + 60;
        int d = rnd.Next(100) + 80;
        Meal br = new Meal(enumMeal.b, b);
        Meal lu = new Meal(enumMeal.l, l);
        Meal di = new Meal(enumMeal.d, d);
        Day day = new Day(br, lu, di);
        Days.Add(day);
        sum += day.Calories;
    }
    decimal avg = sum / 7;
    foreach (Day d in Days.OrderBy(x => x.Calories))
        System.Diagnostics.Debug.WriteLine(d.Calories);
    System.Diagnostics.Debug.WriteLine("");

    Day low;
    Day high;
    Day lowLast = null;
    Day highLast = null;
    int count = 0;
    while (true)
    {   // first do high and low
        low = Days.OrderBy(x => x.Calories).FirstOrDefault();
        high = Days.OrderByDescending(x => x.Calories).FirstOrDefault();
        if (lowLast != null && lowLast == low && highLast == high)
            break;
        if (count > 1000)
            break;
        lowLast = low;
        highLast = high;
        count++;               
        Flop(ref high, ref low);
    }
    foreach (Day d in Days.OrderBy(x => x.Calories))
        System.Diagnostics.Debug.WriteLine("{0} {1} {2} {3}", d.Calories, d.B.Calories, d.L.Calories, d.D.Calories);
    System.Diagnostics.Debug.WriteLine("");

    // day a one on one pass
    for (int i = 0; i < 7; i ++)
    {
        for (int j = 0; j < 7; j++)
        {
            if (i == j)
                continue;
            Day d1 = Days[i];
            Day d2 = Days[j];
            Flop(ref d1, ref d2);
        }
    }

    foreach (Day d in Days.OrderBy(x => x.Calories))
        System.Diagnostics.Debug.WriteLine("{0} {1} {2} {3}", d.Calories, d.B.Calories, d.L.Calories, d.D.Calories);
    System.Diagnostics.Debug.WriteLine("");
}
public static void Flop (ref Day high, ref Day low)
{
    if(low.Calories > high.Calories)
    {
        int hold = low.B.Calories;
        low.B.Calories = high.B.Calories;
        high.B.Calories = hold;

        hold = low.L.Calories;
        low.L.Calories = high.L.Calories;
        high.L.Calories = hold;

        hold = low.D.Calories;
        low.D.Calories = high.D.Calories;
        high.D.Calories = hold;

    }
    decimal avg = (low.Calories + high.Calories) / (decimal)2;
    int bDiff = (high.B.Calories - low.B.Calories) < 0 ? 0 : (high.B.Calories - low.B.Calories);
    int lDiff = high.L.Calories - low.L.Calories < 0 ? 0 : (high.L.Calories - low.L.Calories);
    int dDiff = high.D.Calories - low.D.Calories < 0 ? 0 : (high.D.Calories - low.D.Calories);
    // only flop is one does not go past the average  
    if (bDiff > 0 && ((low.Calories + bDiff) < avg || (high.Calories - bDiff) > avg))
    {
        int hold = low.B.Calories;
        low.B.Calories = high.B.Calories;
        high.B.Calories = hold;
    }
    if (lDiff > 0 && ((low.Calories + lDiff) < avg || (high.Calories - lDiff) > avg))
    {
        int hold = low.L.Calories;
        low.L.Calories = high.L.Calories;
        high.L.Calories = hold;
    }
    if (dDiff > 0 && ((low.Calories + dDiff) < avg || (high.Calories - dDiff) > avg))
    {
        int hold = low.D.Calories;
        low.D.Calories = high.D.Calories;
        high.D.Calories = hold;
    }
}
public enum enumMeal {b, l, d};
public class Day
{
    public Meal B { get; set; }
    public Meal L { get; set; }
    public Meal D { get; set; }
    public Decimal Calories { get { return (Decimal)(B.Calories + L.Calories + D.Calories); } }
    public Day (Meal b, Meal l, Meal d )
    {
        B = b;
        L = l;
        D = d;
    }
}
public class Meal
{
    public enumMeal Type { get; set; }
    public int  Calories { get; set; }
    public Meal (enumMeal meal, int calories)
    {
        Type = meal;
        Calories = calories;
    }
}   
paparazzo
sumber
1
apakah ada cara Anda bisa menambahkan penjelasan atau komentar ke kode untuk mendapatkan jawaban yang lebih bermanfaat / menerangi? Saya pikir saya mengerti apa yang terjadi di sana tetapi saya tidak yakin.
Adam Wells
@AdamWells Saya menambahkan beberapa komentar. Apa yang tidak kamu mengerti?
paparazzo
Itu hanya tidak mengklik dengan gagal. Masuk akal sekarang, terima kasih!
Adam Wells
Saya bahkan tidak tahu apakah ini kode Java. Apakah itu ? Maaf, hari Java dan Cx saya jauh di belakang saya. Di mana letak utamanya?
Arthur Havlicek
@ArthurHavlicek Kode C #. Mereka terlihat sangat sama.
paparazzo
0

Pertama hitung jumlah kalori rata-rata per makan. Kemudian hitung rata-rata hitungan colorie per hari. Ini akan menjadi metrik yang dapat diukur seseorang. Selanjutnya macam-macam makanan.

Sekarang pilih saja makanan tertinggi dan terendah dari jenis itu. Jika makan dalam slot waktu yang sama Anda harus pergi ke terendah berikutnya atau tertinggi sampai Anda menemukan makanan yang tidak ada dalam slot waktu itu (makan malam, dll.). Lakukan ini untuk 4 kali pertama (hi / rendah). Pada jam ke-5, pilihlah makanan yang membuat Anda paling dekat dengan rata-rata. Hemat 5 porsi ke ember terpisah. Bilas dan ulangi sebanyak 7 kali.

Ini akan menjadi set makanan awal Anda. Ini akan sangat merata. Jika Anda ingin distribusi optimal, beberapa perbaikan lebih lanjut dapat dilakukan dengan makanan ke-5.

Periksa ember makanan ke-5 dan cobalah menukar makanan makanan ke-5 di antara hari-hari untuk melihat apakah makanannya bahkan lebih jauh. Anda masih harus menerapkan aturan yang sama (tidak lebih dari satu kali makan per waktu). Seseorang mungkin atau mungkin tidak mendapatkan set lebih banyak. Gunakan rata-rata yang dihitung sebelumnya untuk melihat apakah ada peningkatan atau tidak. Akan ada kombinasi yang jauh lebih sedikit karena 4 makanan pertama ditetapkan berdasarkan tinggi / rendah.

Jon Raynor
sumber