I'm adapting an open source code of Moletrust algorithm implementation from https://github.com/466152112/HappyResearch/blob/master/happyresearch/src/main/java/happy/research/utils/MoleTrust.java
the change that I should make to calculate the trust value is adapted from this paper "Trust-aware Collaborative Filtering for Recommender Systems" written by Moletrust creators. They calculate the trust as follows
"a user at distance n from source user will have a predicted trust value of (d − n + 1)/d" where d is the maximum propagation distance.
The result that I get is either 1 or zero which is not correct. Hope that you can help me find the error.
public static HashMap<String ,Double> MoleTrustAlg ( HashMap<String,HashMap<String,Double>> trust_data,String sourceUser , int horizon)
{
// all the visited nodes
List<String> nodes = new ArrayList<>(40163);
// source user - edges[target users - trust value]
Map<String, Map<String, Double>> edges = new HashMap<>(40163);
/* Step 1: construct directed graphic and remove cyclic */
int dist = 0;
List<String>[] users = new List[horizon + 1];
users[dist] = new ArrayList<>();
users[dist].add(sourceUser);
nodes.add(sourceUser);
// Denote su: source user; tu: target user
while (dist < horizon)
{
dist++;
users[dist] = new ArrayList<>();
for (String su : users[dist - 1])
{
Map<String, Double> tns = trust_data.get(su);
if (tns == null) continue; // no trusted neighbours
for (String tn : tns.keySet())
{
if (!nodes.contains(tn) && !users[dist].contains(tn) && !users[dist - 1].contains(tn))
{
users[dist].add(tn);
}
}
}
for (String su : users[dist - 1])
{
Map<String, Double> tns = trust_data.get(su);
if (tns == null) continue;
for (String tu : tns.keySet())
{
if (!nodes.contains(tu) && users[dist].contains(tu))
{
Map<String, Double> tuTrusts;
if (edges.containsKey(su)) tuTrusts = edges.get(su);
else tuTrusts = new HashMap<>();
double trustValue = tns.get(tu);
tuTrusts.put(tu, trustValue);
edges.put(su, tuTrusts);
}
}
}
}
/* Step 2: Evaluate trust score */
dist = 0;
//double threashold = 0.5;
// trusted neighbours - trust score map
HashMap<String, Double> trustScores = new HashMap<>();
trustScores.put(sourceUser, 1.0);
while (dist < horizon)
{
dist++;
for (String su : users[dist - 1])
{
Map<String, Double> tns = trust_data.get(su);
if (tns == null) continue;
for (String tu : tns.keySet())
{
double trust_value = (horizon -dist +1) / horizon;
trustScores.put(tu, trust_value);
}
}
}
trustScores.remove(sourceUser);
return trustScores;
}
GOT IT
The reason is
double trust_value = (horizon -dist +1) / horizon;
as horizon and dist are integers, I need to cast it before assigning the result to the double variable.
double trust_value = (double) (horizon -dist +1) / horizon;
Related
i have list of items in cart(assume each letter is an item)
cart list = a,s,d,f,a,s,d,f,a
here is the promotion
buy 1 a and get 2 d Free of Charge(in the below logic 1 is srcNum and 2 is tarNum)
the logic should be progressive.(for each a 2d should be free).
for the above input o/p should be d,d
i made some thing like below. but not working
any help appreciated
Iterator tempIterator = tempList.iterator();
boolean targetCheck = false;
int check=0;
boolean runCompleted = false;
while (!runCompleted && tempIterator.hasNext()){
String itemCode = (String) tempIterator.next();
if(!targetCheck && targetItemsList.contains(itemCode) && check < tarNum){
tempIterator.remove();
check++;
}
else if (check >= tarNum && targetCheck == false) {
check = 0;
targetCheck = true;
}
else if (check < srcNum && targetCheck == true) {
tempIterator.remove();
Integer discountQuantity = discountedItems.get(itemCode);
if(null==discountQuantity) {
discountQuantity = 1;
}else {
discountQuantity++;
}
discountedItems.put(itemCode,discountQuantity);
check++;
}
else if (check >= srcNum && targetCheck == true) {
check = 0;
targetCheck = false;
}
if(tempList.size()==0){
runCompleted = true;
}else{
tempIterator = tempIterator = tempList.iterator();
}
Your discount must be stored: item a has 2 d free. Since java 9 you can use the record class.
record Discount(int itemCode, int free) {};
Map<Integer, Discount> itemCodeToDiscountMap = new HashMap<>();
This becomes a bit more complex if 2 a 1 d free or even 2 a 1 a free. But not unduly.
You have a chaotic cart, something like:
List<Item> cartList = new ArrayList<>();
This is best kept in a map of item code to quantity.
Map<Integer, Integer> itemCodeToQuantityMap = new HashMap<>();
At the end of your evaluation you will have:
Map<Integer, Integer> itemsToPay = new HashSet<>();
Map<Integer, Integer> itemsFree = new HashSet<>();
Map<Integer, Integer> itemsCouldTakeFree = new HashSet<>();
So [a, a, b, d, d, d] with 1a=2d free:
itemsToPay = [a -> 2, b -> 1]
itemsFree = [d -> 3]
itemsCouldTakeFree = [d -> 1] "You can fetch 1 d free"
The first step, simplifying the cart data:
List<Item> cartList = new ArrayList<>();
...
Map<Integer, Integer> itemCodeToQuantityMap = new HashMap<>();
for (Item item: cartList) {
Item oldItem = itemCodeToQuantityMap.get(item.itemCode);
...
itemCodeToQuantityMap.get(item.itemCode, ...);
}
And then
itemsToPay.putAll(itemCodeToQuantityMap);
for (Map.Entry<Integer, Integer> entry: itemCodeToQuantityMap.entrySet()) {
int itemCode = entry.getKey();
int quantity = entry.getValue();
Discount discount = itemCodeToDiscountMap.get(itemCode);
...
}
First making a copy of itemCodeToQuantityMap into itemsToPay means you need not alter itemCodeToQuantityMap but can discount in / subtract from itemsToPay.
As this reeks of home work, I leave it at that. Just the tips:
Use data structures easying the work; here having the quantity of every item.
So one needs a Map.
I am building a program that decides which group of people will survive and trace all the attributes. Therefore, I use one ArrayList to save the survived attributes, and another save the total attributes for the coming survival ratio calculation.
I've confirmed that my attributes are saved correctly, but I don't know what's wrong with my hashmap code. It showed everything 0.00. My idea is to find the frequency of each attribute, and compute the ratio based on its frequency and the key. Any help or hint is highly appreciated.
Map<Object, Double> totalCounts = new HashMap<>();
Map<Object, Double> surviveCounts = new HashMap<>();
//put total characteristics in the map
for (Object element : total) {
if (totalCounts.containsKey(element)) {
totalCounts.put(element, totalCounts.get(element) + (double) 1);
} else {
totalCounts.put(element,(double) 1);
}
}
//put survived characteristics in the map
for (Object survive : survival) {
if (surviveCounts.containsKey(survive)) {
surviveCounts.put (survive, surviveCounts.get(survive) + (double) 1);
} else {
surviveCounts.put(survive, (double) 1);
}
}
for (Map.Entry<Object, Double> entrySurvive : surviveCounts.entrySet()) {
Object surviveKey = entrySurvive.getKey();
Double surviveValue = entrySurvive.getValue();
for (Map.Entry<Object, Double> entryTotal : totalCounts.entrySet()) {
Object totalKey = entryTotal.getKey();
Double totalValue = entryTotal.getValue();
if (totalKey.equals(surviveKey)) {
double percent = surviveValue / totalValue;
surviveData.put(surviveKey, percent);
} else {
surviveData.put(totalKey, (double) 0);
}
}
}
//print out the ratio
surviveData.entrySet().stream()
.sorted((k1, k2) -> -k1.getValue().compareTo(k2.getValue()))
.forEach(k -> System.out.println(k.getKey().toString().toLowerCase() + ": " +String.format("%.2f", k.getValue())));
Just update if surviceKey is equal to totalKey
for (Map.Entry<Object, Double> entrySurvive : surviveCounts.entrySet()) {
Object surviveKey = entrySurvive.getKey();
Double surviveValue = entrySurvive.getValue();
for (Map.Entry<Object, Double> entryTotal : totalCounts.entrySet()) {
Object totalKey = entryTotal.getKey();
Double totalValue = entryTotal.getValue();
if (totalKey.equals(surviveKey)) {
double percent = surviveValue / totalValue;
surviveData.put(surviveKey, percent);
}
}
}
Or you can just write,
Map<Object, Double> surviveData = surviveCounts.keySet().stream()
.filter(totalCounts::containsKey)
.collect(
Collectors.toMap(k -> k, k->surviveCounts.get(k)/totalCounts.get(k)));
If using the nested for loop, there is 100% that totalKey and surviveKey will be different. Thus:
for (Map.Entry<Object, Double> entrySurvive : surviveCounts.entrySet()) {
Object surviveKey = entrySurvive.getKey();
Double surviveValue = entrySurvive.getValue();
for (Map.Entry<Object, Double> entryTotal : totalCounts.entrySet()) {
Object totalKey = entryTotal.getKey();
Double totalValue = entryTotal.getValue();
if (totalKey.equals(surviveKey)) {
double percent = surviveValue / totalValue;
surviveData.put(surviveKey, percent);
} else {
//will lead to all attributes' ratio 0.00
surviveData.put(totalKey, (double) 0);
}
}
}
The correct way to put those dead people is:
for (Map.Entry<Object, Double> entrySurvive : surviveCounts.entrySet()) {
Object surviveKey = entrySurvive.getKey();
double surviveValue = entrySurvive.getValue();
for (Map.Entry<Object, Double> entryTotal : totalCounts.entrySet()) {
Object totalKey = entryTotal.getKey();
double totalValue = entryTotal.getValue();
if (totalKey.equals(surviveKey)) {
double percent = surviveValue / totalValue;
surviveData.put(surviveKey, percent);
}
}
}
// if the surviveCounts' keys aren't in the totalCount's key
// it means they're not even survive once
for (Map.Entry<Object, Double> entryTotal : totalCounts.entrySet()) {
Object totalKey = entryTotal.getKey();
if (!surviveCounts.containsKey(entryTotal.getKey())) {
surviveData.put(totalKey, (double) 0);
}
}
I have an unsorted list with float values. I'm able to create graph from that.
But now, I want to create batches based on up and downs in that graph.
For example, I've an list like below
[6.17, 6.13, 6.12, 6.19, 6.2, 6.21, 6.28, 6.17, 6.2, 6.28]
First batch will be decreasing from 6.17 to 6.12 (index 0 to index 2).
Then second batch will be increasing from 6.12 to 6.28(index 3 to index 6)
All I can think of is to create two methods
increasing(List values) - to get all incremental values
decreasing(List values) - to get all decremental values
Call decreasing() method in increasing() method whenever I find sudden drop in values with sublist from last accessed element and vice-versa
But I don't think this is good idea.
Please find the graph image for reference
I've an object TimeAnalysis which contains start and end values.
In first case start=6.17 and end=6.12.
In second case start=6.12 and end=6.28
I want to get list of TimeAnalysis objects.
To actually split them up you can use Math.signum.
private List<List<Double>> splitAtInflectionPoints(List<Double> data) {
List<List<Double>> split = new LinkedList<>();
int start = 0;
for (int i = 1; i < data.size() - 1; i++) {
double leftSlope = Math.signum(data.get(i) - data.get(i - 1));
double rightSlope = Math.signum(data.get(i + 1) - data.get(i));
if (leftSlope != rightSlope) {
split.add(data.subList(start, i + 1));
start = i;
}
}
if (start < data.size()) {
split.add(data.subList(start, data.size()));
}
return split;
}
private void test() {
List<Double> data = Arrays.asList(6.17, 6.13, 6.12, 6.19, 6.2, 6.21, 6.28, 6.17, 6.2, 6.28);
for (List<Double> run : splitAtInflectionPoints(data)) {
System.out.println(run);
}
}
Prints:
[6.17, 6.13, 6.12]
[6.12, 6.19, 6.2, 6.21, 6.28]
[6.28, 6.17]
[6.17, 6.2, 6.28]
You can create a class that stores the list of values and type of Batch.
class Batch {
enum BatchType {
INCREASING,
DECREASING
};
BatchType batchType;
List<Float> values;
}
Now you can have a method called splitIntoBatches which returns a list of Batch.
public List<Batch> splitIntoBatches(List<Float> values) {
// Traverse through the list once and create list of batches.
}
You can loop through elements in your array and track if it's increasing or decreasing or possibly the same.
I used TimeAnalysis class you mentioned and wrote a static method splitList().
It is to split the list of time floats into list of TimeAnalysis.
public static List<TimeAnalysis> splitList(List<Float> timeList) {
if(timeList.size() == 0) return new ArrayList<>();
else if(timeList.size() == 1) {
List<TimeAnalysis> batches = new ArrayList<>();
batches.add(new TimeAnalysis(timeList.get(0), timeList.get(0)));
return batches;
}
ArrayList<TimeAnalysis> batches = new ArrayList<>();
// 0: same, 1: inc, 2: dec
int type = -1;
TimeAnalysis lastBatch = new TimeAnalysis(timeList.get(0), timeList.get
batches.add(lastBatch);
timeList.remove(0);
for(float t : timeList) {
switch(type) {
case 0: // same
if(t > lastBatch.end) { // inc
lastBatch = new TimeAnalysis(lastBatch.end, t);
batches.add(lastBatch);
type = 1;
} else if(t < lastBatch.end) { // dec
lastBatch = new TimeAnalysis(lastBatch.end, t);
batches.add(lastBatch);
type = 2;
}
break;
case 1: // inc
if(t > lastBatch.end) { // inc
lastBatch.end = t;
} else if(t < lastBatch.end) { // dec
lastBatch = new TimeAnalysis(lastBatch.end, t);
batches.add(lastBatch);
type = 2;
} else { // same
lastBatch = new TimeAnalysis(lastBatch.end, t);
batches.add(lastBatch);
type = 0;
}
break;
case 2: // dec
if(t > lastBatch.end) { // inc
lastBatch = new TimeAnalysis(lastBatch.end, t);
batches.add(lastBatch);
type = 1;
} else if(t < lastBatch.end) {
lastBatch.end = t;
} else {
lastBatch = new TimeAnalysis(lastBatch.end, t);
batches.add(lastBatch);
type = 0;
}
break;
default:
if(t > lastBatch.end) type = 1;
else if(t < lastBatch.end) type = 2;
else type = 0;
lastBatch.end = t;
break;
}
}
return batches;
}
When I run:
Scanner in = new Scanner(System.in);
ArrayList<Float> input = new ArrayList<>();
for(int i=0; i<10; i++) input.add(in.nextFloat());
List<TimeAnalysis> output = TimeAnalysis.splitList(input);
for(TimeAnalysis batch : output) System.out.println("start: " + batch.start + ", end: " + batch.end);
and give your data as input, I get:
start: 6.17, end: 6.12
start: 6.12, end: 6.28
start: 6.28, end: 6.17
start: 6.17, end: 6.28
I want to sort some data. At the moment the data is stored in a map. I know, I can't sort data in a map by value. I calculate a soccer schedule like that:
TeamName, G+, G-, P
I want to sort first by P, then by G+, then by G-.
Every k,v is in a map like this:
map.put(e.getString("team_id"), 0);
map.put(e.getString("team_id")+"G+", 0);
map.put(e.getString("team_id")+"G-", 0);
I know that the data structure is really bad! I think it is better to get the values into a Collection to do a collection.sort. But How can I do that?
Here is my code (the code works fine, but is unsorted and badly coded):
HashMap<String, Integer> map = new HashMap<String, Integer>();
HashMap<String, String> tab = new HashMap<String, String>();
for(int i=0; i<teams.length(); i++){
JSONObject e = teams.getJSONObject(i);
//get TeamID
map.put(e.getString("team_id"), 0);
//Goals +
map.put(e.getString("team_id")+"G+", 0);
//Goals -
map.put(e.getString("team_id")+"G-", 0);
//standings.add(map);
//Log.e("Team7", String.valueOf(map.get("7")));
//Log.e("Team7", e.getString("team_id"));
}
for(int i=0; i<matchdata.length(); i++){
JSONObject e = matchdata.getJSONObject(i);
//calculate Points
int myVarGoal1 = Integer.valueOf(e.getString("points_team1"));
int myVarGoal2 = Integer.valueOf(e.getString("points_team2"));
if ((myVarGoal1) > (myVarGoal2)){
myPoint1 = 3;
myPoint2 = 0;
}
if ((myVarGoal1) < (myVarGoal2)){
myPoint1 = 0;
myPoint2 = 3;
}
if ((myVarGoal1) == (myVarGoal2)){
myPoint1 = 1;
myPoint2 = 1;
}
int calc1 = (map.get(e.getString("id_team1")) + myPoint1);
int calc2 = (map.get(e.getString("id_team2")) + myPoint2);
map.put("id", Integer.valueOf(i));
map.put(e.getString("id_team1"), calc1);
map.put(e.getString("id_team2"), calc2);
//calculate Goals
int calcGoal1 = (map.get(e.getString("id_team1")+"G+") + myVarGoal1);
int calcGoal2 = (map.get(e.getString("id_team1")+"G-") + myVarGoal2);
int calcGoal3 = (map.get(e.getString("id_team2")+"G+") + myVarGoal2);
int calcGoal4 = (map.get(e.getString("id_team2")+"G-") + myVarGoal1);
map.put(e.getString("id_team1")+"G+", calcGoal1);
map.put(e.getString("id_team1")+"G-", calcGoal2);
map.put(e.getString("id_team2")+"G+", calcGoal3);
map.put(e.getString("id_team2")+"G-", calcGoal4);
//standings.add(map);
//Log.e("TeamID", e.getString("id_team1"));
//Log.e("PointsTeam7", String.valueOf(map.get("7")));
//Log.e("GaolsTeam7", String.valueOf(map.get("7G-")));
}
for(int i=0; i<teams.length(); i++){
JSONObject e = teams.getJSONObject(i);
String myTeamID = e.getString("team_id");
int Gdif = (map.get(myTeamID+"G+")) - (map.get(myTeamID+"G-"));
tab.put(myTeamID, e.getString("team_name") +","+ map.get(myTeamID) +","+ (map.get(myTeamID+"G+")) +":"+ (map.get(myTeamID+"G-")) +" "+ Gdif);
//Log.e("Team7", String.valueOf(tab.get("7")));
//Log.e("Team7", e.getString("team_id"));
strGoals+="\n" + String.valueOf(tab.get(myTeamID));
}
It sounds like you need to first create your own class to hold related data as one single object. The exact name of the class depends on what the data is. Maybe SoccerTeam or SoccerSchedule. After you create this class, you can implement the Comparable interface or create a Comparator object that defines the sorting order.
I think what you're looking for is a TreeMap and a Comparator. Can you switch to using a TreeMap instead? It works just like a HashMap, but will automatically sort your keys for you. Then you can use a Comparator like this:
Map<String, Integer> map = new HashMap<String, Integer>();
..... do stuff .....
TreeMap<String, Integer> treeMap = new TreeMap<String, Integer>(new Comparator<String>()
{
#Override
public int compare(String lhs, String rhs)
{
// return 1 if lhs > rhs
// return 0 if lhs = rhs
// return -1 if lhs < rhs
if (lhs == null && rhs == null) return 0;
if (lhs == null) return -1;
if (rhs == null) return 1;
if ((lhs.endsWith("P") && (rhs.endsWith("P")))
|| (lhs.endsWith("G+") && (rhs.endsWith("G+")))
|| (lhs.endsWith("G-") && (rhs.endsWith("G-"))))
{
return lhs.compareTo(rhs);
}
else if (lhs.endsWith("P"))
{
return -1;
}
else if (rhs.endsWith("P"))
{
return 1;
}
else
{
String lastLeftChar = lhs.substring(lhs.length()-1);
String lastRightChar = rhs.substring(rhs.length()-1);
return lastLeftChar.compareTo(lastRightChar);
}
}
});
treeMap.putAll(map);
// Now your treeMap is sorted by the keys!
I'm doing some sentiment analysis using SentiWordNet and I referred to the post here How to use SentiWordNet . However, I'm getting a score of 0.0 despite trying out various inputs. Is there anything I'm doing wrong here? Thanks!
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
public class SWN3 {
private String pathToSWN = "C:\\Users\\Malcolm\\Desktop\\SentiWordNet_3.0.0\\home\\swn\\www\\admin\\dump\\SentiWordNet_3.0.0.txt";
private HashMap<String, Double> _dict;
public SWN3(){
_dict = new HashMap<String, Double>();
HashMap<String, Vector<Double>> _temp = new HashMap<String, Vector<Double>>();
try{
BufferedReader csv = new BufferedReader(new FileReader(pathToSWN));
String line = "";
while((line = csv.readLine()) != null)
{
String[] data = line.split("\t");
Double score = Double.parseDouble(data[2])-Double.parseDouble(data[3]);
String[] words = data[4].split(" ");
for(String w:words)
{
String[] w_n = w.split("#");
w_n[0] += "#"+data[0];
int index = Integer.parseInt(w_n[1])-1;
if(_temp.containsKey(w_n[0]))
{
Vector<Double> v = _temp.get(w_n[0]);
if(index>v.size())
for(int i = v.size();i<index; i++)
v.add(0.0);
v.add(index, score);
_temp.put(w_n[0], v);
}
else
{
Vector<Double> v = new Vector<Double>();
for(int i = 0;i<index; i++)
v.add(0.0);
v.add(index, score);
_temp.put(w_n[0], v);
}
}
}
Set<String> temp = _temp.keySet();
for (Iterator<String> iterator = temp.iterator(); iterator.hasNext();) {
String word = (String) iterator.next();
Vector<Double> v = _temp.get(word);
double score = 0.0;
double sum = 0.0;
for(int i = 0; i < v.size(); i++)
score += ((double)1/(double)(i+1))*v.get(i);
for(int i = 1; i<=v.size(); i++)
sum += (double)1/(double)i;
score /= sum;
String sent = "";
if(score>=0.75)
sent = "strong_positive";
else
if(score > 0.25 && score<=0.5)
sent = "positive";
else
if(score > 0 && score>=0.25)
sent = "weak_positive";
else
if(score < 0 && score>=-0.25)
sent = "weak_negative";
else
if(score < -0.25 && score>=-0.5)
sent = "negative";
else
if(score<=-0.75)
sent = "strong_negative";
_dict.put(word, score);
}
}
catch(Exception e){e.printStackTrace();}
}
public Double extract(String word)
{
Double total = new Double(0);
if(_dict.get(word+"#n") != null)
total = _dict.get(word+"#n") + total;
if(_dict.get(word+"#a") != null)
total = _dict.get(word+"#a") + total;
if(_dict.get(word+"#r") != null)
total = _dict.get(word+"#r") + total;
if(_dict.get(word+"#v") != null)
total = _dict.get(word+"#v") + total;
return total;
}
public static void main(String[] args) {
SWN3 test = new SWN3();
String sentence="Hello have a Super awesome great day";
String[] words = sentence.split("\\s+");
double totalScore = 0;
for(String word : words) {
word = word.replaceAll("([^a-zA-Z\\s])", "");
if (test.extract(word) == null)
continue;
totalScore += test.extract(word);
}
System.out.println(totalScore);
}
}
Here's the first 10 lines of SentiWordNet.txt
a 00001740 0.125 0 able#1 (usually followed by `to') having the necessary means or skill or know-how or authority to do something; "able to swim"; "she was able to program her computer"; "we were at last able to buy a car"; "able to get a grant for the project"
a 00002098 0 0.75 unable#1 (usually followed by `to') not having the necessary means or skill or know-how; "unable to get to town without a car"; "unable to obtain funds"
a 00002312 0 0 dorsal#2 abaxial#1 facing away from the axis of an organ or organism; "the abaxial surface of a leaf is the underside or side facing away from the stem"
a 00002527 0 0 ventral#2 adaxial#1 nearest to or facing toward the axis of an organ or organism; "the upper side of a leaf is known as the adaxial surface"
a 00002730 0 0 acroscopic#1 facing or on the side toward the apex
a 00002843 0 0 basiscopic#1 facing or on the side toward the base
a 00002956 0 0 abducting#1 abducent#1 especially of muscles; drawing away from the midline of the body or from an adjacent part
a 00003131 0 0 adductive#1 adducting#1 adducent#1 especially of muscles; bringing together or drawing toward the midline of the body or toward an adjacent part
a 00003356 0 0 nascent#1 being born or beginning; "the nascent chicks"; "a nascent insurgency"
a 00003553 0 0 emerging#2 emergent#2 coming into existence; "an emergent republic"
Usually the SentiWord.txt file comes with a weird format.
You need to remove the first part of it (which includes comments and instructions) and the last two lines:
#
EMPTY LINE
The parser doesn't know how to handle these situations, if you delete these extra two lines you'll be fine.