2011-10-21 15 views
1

私は以下の問題があります。私はPHPの& mysqlを使ってダイエット計画を立てたい。 私は、次があります。最良の結果と一致するダイエッ​​トプランのロジック

  • パン:タンパク質、炭水化物の2グラム、脂肪
  • の4グラムの1グラム砂糖:タンパク質、炭水化物の6グラム、脂肪の1グラム
  • コーヒーの3グラム:タンパク質の8グラム、炭水化物の2グラム、脂肪
  • 肉の2グラム:タンパク質、炭水化物の0グラム、脂肪の12グラムの7グラム
  • ミルク:タンパク質、炭水化物の12グラム、脂肪の2グラムの16グラム

上記を持って、私は以下の合計に一致する上記の最良の組み合わせを見出したい:

目的:炭水化物41g - 脂肪120g。

などの結果を示しています。私はPHP & mysqlのに問題を持っていない

などの肉の5枚、ミルクの3枚を、。私はこの問題の背後にある論理を見つけようとします。

答えて

1

ここではうまくいくはずの強力な解決策があります。これは、SQL Serverで書かれたSQLスクリプトで、MySqlで動作するはずですが、マイナーな変更が必要な場合があります。最適なソリューションを見つける前に、可能なすべてのアイテムの組み合わせを繰り返します。

-- Limits by protein/carb/fat 
DECLARE @protein_limit INT 
SET @protein_limit = 160 

DECLARE @carb_limit INT 
SET @carb_limit = 90 

DECLARE @fat_limit INT 
SET @fat_limit = 120 



-- Table holding valid items 
DECLARE @items TABLE 
(
    id INT IDENTITY(1,1), 
    name VARCHAR(50), 
    protein INT, 
    carb INT, 
    fat INT 
) 

INSERT INTO @items 
     SELECT 'Bread', 1, 2, 4 
UNION SELECT 'Sugar', 3, 6, 1 
UNION SELECT 'Coffee', 8, 2, 2 
UNION SELECT 'Meat', 7, 0, 12 
UNION SELECT 'Milk', 16, 12, 2 


DECLARE @item_count INT 
SELECT @item_count = COUNT(*) 
FROM @items 


-- From: http://stackoverflow.com/questions/9507635/pivot-integer-bitwise-values-in-sql/9509598#9509598 
DECLARE @bits TABLE 
(
    number INT, 
    [bit] INT, 
    value INT 
) 


; with AllTheNumbers as (
    select cast (POWER(2, @item_count) as int) - 1 Number 
    union all 
    select Number - 1 
    from AllTheNumbers 
    where Number > 0 
), 
Bits as (
    select @item_count - 1 Bit 
    union all 
    select Bit - 1 
    from Bits 
    where Bit > 0 
) 
INSERT INTO @bits (number, [bit], value) 
select *, case when (Number & cast (POWER(2, Bit) as int)) != 0 then 1 else 0 end 
from AllTheNumbers cross join Bits 
order by Number, [Bit] desc 


-- Table to hold trials - brute force! 
DECLARE @trials TABLE 
(
    trial_id INT, 
    item_id INT, 
    item_quantity INT 
) 


DECLARE @trial_max INT 
SET @trial_max = (@protein_limit + @carb_limit + @fat_limit) * (POWER(2, @item_count)) 

DECLARE @trial_id INT 
SET @trial_id = 1 

DECLARE @base_quantity INT 

WHILE @trial_id <= @trial_max 
BEGIN 

    SET @base_quantity = FLOOR((@trial_id/POWER(2, @item_count))) 

    INSERT INTO @trials (trial_id, item_id, item_quantity) 
    SELECT @trial_id + 1 + b.number 
     , id 
     , @base_quantity + b.value 
    FROM @items a 
    JOIN @bits b 
     ON a.id = b.[bit] + 1 



    --UPDATE @trials 
    --SET item_quantity = @base_quantity + (@trial_id % item_id) 
    --WHERE trial_id = @trial_id 

    SET @trial_id = @trial_id + POWER(2, @item_count) 

END 


-- Get results of each trial 
SELECT * 
FROM @trials a 
JOIN @items b 
    ON a.item_id = b.id 
ORDER BY a.trial_id 

-- Use the trial_id field to reference the results of the previous select 
SELECT * 
FROM 
(
    SELECT trial_id 
     , SUM(protein * item_quantity) AS protein_total 
     , SUM(carb * item_quantity) AS carb_total 
     , SUM(fat * item_quantity) AS fat_total 
    FROM @trials a 
    JOIN @items b 
     ON a.item_id = b.id 
    GROUP BY trial_id 
) a 
WHERE protein_total <= @protein_limit 
    AND carb_total <= @carb_limit 
    AND fat_total <= @fat_limit 
ORDER BY ((@protein_limit - protein_total) + (@carb_limit - carb_total) - (@fat_limit - fat_total)) ASC 


-- This last query gets the best fit 
SELECT c.name 
    , b.item_quantity 
FROM 
(
    SELECT * 
     , ROW_NUMBER() OVER (ORDER BY ((@protein_limit - protein_total) + (@carb_limit - carb_total) - (@fat_limit - fat_total)) ASC) AS rn 
    FROM 
    (
     SELECT trial_id 
      , SUM(protein * item_quantity) AS protein_total 
      , SUM(carb * item_quantity) AS carb_total 
      , SUM(fat * item_quantity) AS fat_total 
     FROM @trials a 
     JOIN @items b 
      ON a.item_id = b.id 
     GROUP BY trial_id 
    ) a 
    WHERE protein_total <= @protein_limit 
     AND carb_total <= @carb_limit 
     AND fat_total <= @fat_limit 
) a 
JOIN @trials b 
    ON a.trial_id = b.trial_id 
JOIN @items c 
    ON b.item_id = c.id 
WHERE a.rn = 1 

これは3つの結果を返し、それぞれ異なる方法でデータを表示します。

動作するかどうか教えてください!

0

問題自体には欠陥があります。行き過ぎることなくそれらの目標にできるだけ近づくように努力していますか?あなたは単にそれらの数字に近い「解決策」を探していますか?あなたが受け入れられる答えとなるものをどのように定義するかによって、これは非常に簡単で、非常に非常に非常に難しい問題です。

たとえば、1gの各タンパク質、炭水化物、脂肪を含む新しい成分を加えます。また、1gのタンパク質、0個の炭水化物/脂肪、1gの炭水化物0gタンパク質/脂肪などを含む3種類の成分をそれぞれ追加します。ここでは、両方とも目標と正確に一致するだろう。

タンパク質の食物があなたには重いと仮定して、1g/1g/1gの栄養素をもっとたくさん用意しておきましょう。目標を達成できないが、15杯のミルクを飲むことはありません。

ナップザックの問題は素晴らしいスタートですが、この問題を解決する方法は数百万種類あります。ソリューションを試してコードを作成する場合は、具体的な問題を解決し、それを拡張しようとすることをおすすめしますあなたは何がボンネットの下で起こっているのか理解しています。

関連する問題