問題解決-多段歯ブラシ販売


https://programmers.co.kr/learn/courses/30/lessons/77486

多段歯ブラシ販売


問題の説明
民浩は多段階組織を利用して歯ブラシを販売している.販売員が歯ブラシを販売すると、その利益はピラミッドを通じて少しずつ分配される形の販売ネットワークになる.販売がある程度に達した後、民浩は組織を経営しており、組織の中で誰がどれだけの利益を得たのか知りたいと思っている.例えば、民浩が運営する多段歯ブラシ販売組織を下図に示す.

ミンホはセンターで、青いボックスは8人の店員がいることを示しています.誰もが自分を組織に参加させる推薦者に接続し、ピラミッド式の構造を形成している.組織の収益配分ルールは簡単です.すべての販売員は歯ブラシ販売による利益から10%を計算し、参加組織の推薦者に自分を割り当て、残りは自分が所有する.各販売員は、歯ブラシの販売によって生じた利益と、組織に参加することを推奨した販売員の10%の利益から利益を得ることができます.あなたの身に起こった利益も同じルールで推薦者に割り当てられます.ただし、10%を計算すると、1元単位で計算され、10%の金額が1元未満を計算すると、すべての収益が得られます.
たとえば、次の営業記録があるとします.歯ブラシの販売利益は1本100元になる.
販売員販売数量利益金young 121200元john 4400元tod 2200元emily 5500元mary 101000元
販売員youngは1200元の利益を得た.youngはその中の10%に相当する120元を、自分が組織に参加させる推薦者edwardに割り当て、残りの1080元を自分で持っていく.エドワードはyoungからもらった120元のうち、10%の12元をmaryに割り当て、自分で残りの108元を取った.メアリーはエドワードから12元をもらい、10%の1元をセンター(民浩)に割り当て、自分で残りの11元を取った.この状態を下図に示します.

その後、販売員johnは400元の利益を得た.johnは10%の40元を中心に割り当て、自分で残りの360元を取った.この状態を下図に示します.

その後、販売員todは200元、tod自身は180元、推薦人jamieはそのうち10%の20元、jamieの推薦人maryは18元、jamieの推薦人maryは2元を獲得するが、この10%は1単位で購入すると配分された金額がないため、maryは2元を全部持っていく.この状態を下図に示します.

次に、エミリーが歯ブラシを販売することで得た500元の利益は、同じルールでエミリー450元、mary 45元、センター5元に分配された.この状態を下図に示します.

最後に、販売員maryは1000元の利益を得て、そのうち10%の100元をセンターに分配した後、残りの900元は自分で取ります.この状態を下図に示します.

以下に示すように、すべての組織メンバーの利益実現状況統計が完了しました.次の図に示すように、すべての収益を統合します.

これが民浩が知りたい利益分配の状況だ.
各販売者名単位の並び登録、各販売者が多段階組織に参加する他の販売者名単位の並び推薦、販売統計データ単位で販売者名を並べた並び売り、販売統計データ単位で販売数を並べた並び数をパラメータとする.各営業担当者が得た利益のリストを返すソルバを完了してください.営業担当者に割り当てられた利益総額(整数)を計算し、入力した形式で所定の登録に名前が含まれている順序でリストすればよい.
せいげんじょうけん
登録長は10000を超えない.
登録時に民浩の名前はありませんでした.したがって,登録長は民浩を除く組織メンバーの総数である.
参照の長さは登録の長さと同じです.
「推奨」において、iの1番目の名称は、「整列登録」においてiの1番目の販売者を組織に参加させる者の名称である.
誰にも推薦されずに組織に参加した人の場合、「推薦案」には推薦者の名前ではなく「-」と記入します.上記の例ではjohnとmaryがこのような例です.
登録に表示される名前は、参加組織の順に並べられます.
すなわち、ある販売者の名前が登録されたi番目の位置に表示されると、その販売者を組織に加入させる者の名前、すなわち、推奨されるi番目の要素が登録されたj番目の位置に表示されていることが保証される(j売り手の長さは1以上100000以下である.
売り手のi番目の名称は、i番目の販売統計データがどの販売員によって提供されたかを示す.
売り手には重複する名前がある可能性があります.
amountの長さは売り手の長さと同じです.
amountのi番目の数字は、i番目の販売統計データの販売量を表します.
売上高の範囲、すなわちamountの要素の範囲は1以上100以下の自然数である.
歯ブラシを1本販売して得た利益は100元になった.
すべての組織メンバーの名前は、英字小文字(10文字未満)です.
I/O例
enrollreferralselleramountresult["john", "mary", "edward", "sam", "emily", "jaimie", "tod", "young"]["-", "-", "mary", "edward", "mary", "mary", "jaimie", "edward"]["young", "john", "tod", "emily", "mary"][12, 4, 2, 5, 10][360, 958, 108, 0, 450, 18, 180, 1080]["john", "mary", "edward", "sam", "emily", "jaimie", "tod", "young"]["-", "-", "mary", "edward", "mary", "mary", "jaimie", "edward"]["sam", "emily", "jaimie", "edward"][2, 3, 5, 4][0, 110, 378, 180, 270, 450, 0, 0]
I/O例説明
I/O例#1
問題の例.
I/O例#2
これは、問題の例と同じ組織構成に少し異なる販売量統計を適用したものです.収益を割り当てるルールは同じなので、簡単な計算で表に表示される結果を得ることができます.
問題を解く
function solution(enroll, referral, seller, amount) {
    var answer = [];
    let graph = {};
    enroll.forEach((el,i) => {
        if(!graph[referral[i]]) {
            graph[referral[i]] = {
                money: 0,
            }
        }
        if(!graph[el]) {
            graph[el] = {
                referral: referral[i],
                money: 0,
            }
        }
        else {
            graph[el]["referral"] = referral[i]
        }
    })
    seller.forEach((el,i) => {
        let obj = graph[el]
        let money = amount[i] * 100
        while(obj.referral !== undefined) {
            if(money === 0) break;
            let repay = Math.floor(money/10)
            obj["money"] += money - repay
            money = repay
            obj = graph[obj["referral"]]
        }
    })
    for (let prop in graph) {
        answer.push(graph[prop]["money"])
    }
    return answer.slice(1);
}
次からは最初の間違いの答えも保存して、問題を解く過程を書きます.
まずオブジェクトを作成します.
{
  '-': { money: 0 },
  john: { referral: '-', money: 0 },
  mary: { referral: '-', money: 0 },
  edward: { referral: 'mary', money: 0 },
  sam: { referral: 'edward', money: 0 },
  emily: { referral: 'mary', money: 0 },
  jaimie: { referral: 'mary', money: 0 },
  tod: { referral: 'jaimie', money: 0 },
  young: { referral: 'edward', money: 0 }
}
鍵を持つオブジェクトを作成します.このオブジェクトの名前は鍵で、値は推奨者と鍵です.
いったん販売を始めると
まず売り手を指定し、販売で得たお金を取得します.
出品者の推薦がない場合、'-': { money: 0 }<-この時点で重複記事を停止した後
お金がゼロなら、すぐに繰り返しを止めます.
さもないと、あげるべきお金から残りのobjを減らします.moneyを入れ、変数moneyに渡すお金を入れてobjを交換し続けます.
タスクが完了した場合
{
  '-': { money: 0 },
  john: { referral: '-', money: 360 },
  mary: { referral: '-', money: 958 },
  edward: { referral: 'mary', money: 108 },
  sam: { referral: 'edward', money: 0 },
  emily: { referral: 'mary', money: 450 },
  jaimie: { referral: 'mary', money: 18 },
  tod: { referral: 'jaimie', money: 180 },
  young: { referral: 'edward', money: 1080 }
}
こうしてお金を分けました.
その対象のお金をすべて答えに入れ、「-」に対応する0番目のインデックスを削除して返信します.