30 points; to be done individually
You have been hired by Nanosoft. Your boss, Gill Bates, drops
by your spacious cubicle sipping a refreshing and stimulating
Jolt Cola ("All the sugar, and twice the caffeine!").
Gill begins by reminding you that a decider is a program
that takes an input and eventually halts and accepts (says
"True" to its inputs) or rejects (says "False" to its input). For
example, a decider for the prime numbers would take a number,
perhaps encoded in binary, as input and would eventually halt
saying True (it's prime) or False (it's not prime). For
the purposes of this problem, the terms "program," "function,"
and "turing machine" are used interchangeably.
"Drat!" says Gill upon hearing the news. "OK, then, in that
case, I'd like you to write a program called a Regularity
Checker (RC). The Regularity Checker takes as input a
one-input function g (e.g., a Python function or Turing Machine) and the
regularity checker needs to determine
whether or not the set of strings accepted by g is a regular
language. The RC must always halt with an answer of True (g
accepts a regular language) or
False (g does not accept a regular language)."
Prove to Gill that this too is impossible.
Note
that if a function/program/turing machine runs forever on an input, that input
is considered REJECTED for the purposes of defining
the language that the function accepts.
Hint: Often, the exact same construction works
for both this and the previous problem, though the reason that it
works is a bit different in each case.
30 points; to be done individually
For these questions, you will be analyzing the running time of algorithms. We will be interested in worst-case analysis. (The best case is often uninteresting and the average case can be quite difficult to quantify.) You will need to express the worst-case running time using big-O notation. Be sure to show all of your reasoning in each written problem.
Submitting these answers Include your answers to these problems in a plain-text part2.txt file.
for (int i=1 ; i≤n ; i *= 2)
for (int j=0 ; j<i ; ++j)
// constant time work here
for (int i=1 ; i≤n ; ++i)
for (int j=1 ; j<i ; j *= 2)
// constant time work here
reach(A,A,_). % any node is reachable from itself
% below we ask you to explain what this next line is "saying"
reach(A,B,[[X,Y] | R]) :- reach(A,B,R) ; (reach(A,X,R), reach(Y,B,R)).
For example, here are two representative runs:
?- reach( b, a, [[a,b],[b,c],[c,d],[d,e],[e,f],[f,g],[g,a]]).
Yes
?- reach( b, h, [[a,b],[b,c],[c,d],[d,e],[e,f],[f,g],[g,a]]).
No
Note that we are not concerned with generating any variable/value bindings here,
we are only concerned with checking reachability for a fully-bound set
of inputs.
Briefly explain in English what the second reach rule is "saying". Then, write a recurrence relation for T(n), the running time of the above reach function in terms of n, the number of edges in the graph G. Then, use the recurrence-unwinding strategy to "unroll" this recurrence relation in order to find a big-O running time of this version of reachability. Count each logical operation ; (or) and , (and) as one step. Show all of your work!
90 points; may be done in a pair or individually
Part 1: Change, Inc.You have been hired by Change, Inc., a pioneer in the business of making change. Our motto is "Making positive change throughout the world!". Strictly speaking, the change is only "non-negative" since 0 change is possible, but this was a nuance that the PR folks chose to ignore.
Your job is to write software Change, Inc. that will make change in any given currency system using the smallest number of coins/bills. This software will be embedded in cash registers and used to inform tellers how to make change optimally - or will simply automate the dispensing of change via robotic change-makers.
You may assume that you have "unlimited" quantities of each coin/bill, and that you may use any combination - including repeats - in making change for a given quantity.
Your boss, Professor I. Lai, believes that a simple recursive algorithm for this problem will be fast enough for use in the company's cash registers. Although you are skeptical, Prof. Lai is the boss (for now). Your first task, therefore, is to quickly test the viability of a purely recursive approach. To that end, write a Racket function called change that takes two inputs: A list of coins/bills in the currency system (always from smallest to largest) followed by the amount of change to be made. The function simply returns the least number of coins required (but not the actual set of coins to disburse).
Approach: Here, you should employ the use-it-or-lose-it technique! That is, handle the base cases first. Then, consider the results of using (recursively) each of the possible coins in the list... you'll want the minimum of all of these!
Here are two sample inputs and outputs - note that the result depends on the "currency system" being used:
Racket> (change '(1 5 10 25 50) 42)
5
Racket> (change '(1 5 21 35) 42)
2
Note: Recall that Racket has built-in value called +inf.0 that
is larger than any integer. In addition, in order to convert from
floating-point (inexact) values to integer (exact) values, Racket
has a built-in function inexact->exact, e.g.,
Racket> (inexact->exact 42.0)
42
Submit your code in a file named change.rkt.
After the run-time results from the all-recursive change-counter, Dr. Lai has been replaced by the brilliant Dr. Dee Nomination. Dr. D, as she's called, suggests that dynamic programming is likely to solve the problem. Your next task, therefore, is to re-implement the recursive algorithm that you developed in Part 1 using dynamic programming. This time, you should use Java now rather than Racket: Java's arrays will be useful for this re-implementation.
Your program should be called change.java. When run, it will
ask the user for the name of a file with the currency system.
That file will have the following format: The first line contains a single
number, which is the number
of coins and/or bills in the system.
The next lines will contain the values of Each coin/bill in that system,
from 1 upwards. Here is an example of currency amounts (admittedly
fictional, but computationally interesting) -- save these lines
into a plain-text file named ex1.txt:
Here, the first line is the number of currency-amounts to follow (6);
then those currency amount appear one-pre-line afterwards.
6
1
5
9
10
12
20
Feel free to create other currency-amount files, too... . In all cases, you may assume that there will be a "penny" and that they will be in sorted order.
A place to start for file-handling?!
Feel free to adapt the code below to start your program - please use
this class name,
change, to help the graders! You'll see examples
of how to use Scanner
and nextInt -- they are are pretty much all
you'll need here, along with
a loop of some sort...
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
class change
{
public static void main( String[] args )
{
// get keyboard input Object
Scanner kbd = new Scanner(System.in);
// get input from keyboard
System.out.print( "Enter a filename: " );
String filename = kbd.nextLine();
// trim off any whitespace
filename = filename.trim();
System.out.println("Now trying to open " + filename);
// get file input Object via the file:
Scanner file = null;
try { // in case the file's not there
file = new Scanner(new File(filename));
} catch (FileNotFoundException e) {
System.out.println("File " + filename + " not found.");
System.out.println( e );
}
// get integer at the start of the file:
int num_coins = file.nextInt();
System.out.println("Read the # of coins = " + num_coins);
// create an array, coins, to hold the coins:
int[] coins = new int[num_coins];
// here, you'll need to loop in order to read each coin in...
// It's useful for debugging to be able to print an array
System.out.println("The array, coins, is " + Arrays.toString( coins ));
// It's also useful to be able to get more input from the keyboard:
System.out.println("Input an integer and I'll add 1: ");
int amt = kbd.nextInt(); // it will crash if it's not an int!
System.out.println("You entered " + amt + ", one less than " + (amt+1));
}
}
Approach You should take a "bottom-up," dynamic programming approach to solving this instance of the change problem. That is, you should solve the problem for each (integer) amount of change starting at 0 and increasing by 1 up to the user's desired amount. You should keep a table (an array) of these subproblems -- along with an array of the "last coin needed," as we discussed in class on Monday. This approach is much faster, O(N) instead of exponential, than the pure-recursion based approach suggested in Racket, above.
Here is some sample input and output, indicating should happen when you run your program. Note that you may print the coins to be given in any order, not necessarily largest denomination first.
Note As the two examples below indicate, in addition to solving the problem by finding the fewest coins, you should also print out the dynamic programming table and the "last coin needed" table, as discussed in class on Monday.
> java change
Enter a filename: [[user types]] ex1.txt
Now trying to open ex1.txt
Read the number of coins = 6
How much change would you like? [[user types]] 22
OK, searching for change for 22
Minimum # of coins = 2
The coins are 10 12
The DP table was
[0, 1, 2, 3, 4, 1, 2, 3, 4, 1, 1, 2, 1, 2, 2, 2, 3, 2, 2, 2, 1, 2, 2]
The "Last Coin" table was
[0, 1, 1, 1, 1, 5, 1, 1, 1, 9, 10, 1, 12, 1, 5, 5, 1, 5, 9, 9, 20, 1, 10]
> java change
Enter a filename: [[user types]] ex1.txt
Now trying to open ex1.txt
Read the number of coins = 6
How much change would you like? [[user types]] 21
OK, searching for change for 21
Minimum # of coins = 2
The coins are 1 20
The DP table was
[0, 1, 2, 3, 4, 1, 2, 3, 4, 1, 1, 2, 1, 2, 2, 2, 3, 2, 2, 2, 1, 2]
The "Last Coin" table was
[0, 1, 1, 1, 1, 5, 1, 1, 1, 9, 10, 1, 12, 1, 5, 5, 1, 5, 9, 9, 20, 1]
Test your program on some fairly large amounts of change (up to about 1000) in at least two different currency systems. If this version is not a HUGELY dramatic improvement -- in terms of how fast it computes -- over your recursive solution from the Racket solution, check your code again!
Submit your program in change.java.
You've been hired away from Change, Inc. to work for Google and their newest stealth-mode version of their mapping service, which "completely reverses" the online mapping experience, called GoogleSpam. GoogleSpam allows users to estimate the shortest distance among any pair of possible spam-locaitons (nodes) in a map (graph).
In particular, you've been asked to implement the main "smarts" of GoogleSpam, i.e., the all-pairs-shortest-paths algorithm. It reads in a graph from a file and then allow a user to make a query against that graph. (Admittedly, a more complete version might allow more queries, but once you know the shortest path to spam, what more is there to ask?)
Try it first... A .class file is provided in the fw.zip folder. To run the example fw class from the command line, you should be able to use the command java fw from that directory. To run it from Dr. Java, these steps have worked for us:
public static String toStr( int[][] A, int n ) {
String s = "";
for (int row=0 ; row<n ; ++row) {
s += Arrays.toString(A[row]) + "\n";
}
return s;
int[][][] fw = new int[numcities+1][numcities][numcities];
it's better to print slices of them, e.g., toStr(fw[0]),
toStr(fw[1]), and so on... .
> java fw
Enter a filename: [[user input]] map0.txt
Now trying to open map0.txt
Read the number of cities = 3
The FW tables:
fw[0] is
[0, 1, -1]
[-1, 0, 1]
[1, -1, 0]
fw[1] is
[0, 1, -1]
[-1, 0, 1]
[1, 2, 0]
fw[2] is
[0, 1, 2]
[-1, 0, 1]
[1, 2, 0]
fw[3] is
[0, 1, 2]
[2, 0, 1]
[1, 2, 0]
The "previous vertices":
pv is
[0, 0, 1]
[2, 1, 1]
[2, 0, 2]
From what city (1-3)? [[user types]] 3
To what city (1-3)? [[user types]] 2
From city # 3
to city# 2
the minimum cost is 2
And the path is
3 --> 1 --> 2
Warning When querying for a shortest path, this program -- and your program -- should count vertices starting from 1, instead of the traditional start from 0. Indexing from 1 is helpful in this case, because it means you can use the 0 index for other purposes, such as the original graph's adjacency matrix. But be sure to make the arrays you use large enough!
Details on the implementation In a class named fw you should implement the Floyd-Warshall Algorithm for finding the shortest path between every pair of vertices in a graph. Your program should be written in Java. Here are the requirements for your program:
3
0 1 -1
-1 0 1
1 -1 0
Here, the first line of the file contains a positive integer, n,
indicating the number of vertices in the graph.
This is followed by n lines of data, each of which
contains n integers. The integer in row src and
(column) position dst indicates the length of the edge
from vertex src to vertex dst in the graph. If there
is no edge from vertex src to vertex dst then the
length of this edge is "infinity" which is represented by the
value -1.
Note, too, that the length of the edge from vertex src
to dst may be different from the length of the edge from
vertex dst to src, due to traffic,
magic, or other unusual road conditions.
Here are a few tips:
Please submit your solution in a file called fw.java.
There is also an extra-credit assignment, worth up to +50 points, available on Wed. 12/7, and due anytime before Saturday, Dec. 17. It is linked under "Assignment 13."
In case it's useful to copy-and-paste the maps (the different newline characters sometimes cause problems), feel free to do so from these printouts:
map0.txt
3
0 1 -1
-1 0 1
1 -1 0
map1.txt
30
0 12 -1 16 -1 -1 -1 -1 -1 -1 -1 100 -1 119 -1 -1 -1 -1 -1 -1 42 -1 -1 -1 -1 -1 51 -1 -1 -1
-1 0 1 -1 -1 -1 -1 -1 -1 -1 99 -1 201 -1 -1 -1 -1 -1 -1 -1 41 -1 -1 -1 -1 -1 -1 16 -1 119
51 -1 0 1 -1 9 -1 -1 25 -1 -1 76 -1 -1 -1 45 -1 -1 38 31 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 26 0 1 -1 26 -1 -1 -1 29 -1 -1 30 -1 87 -1 -1 -1 -1 -1 -1 -1 41 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
30 -1 17 -1 -1 0 1 -1 -1 42 -1 -1 42 -1 -1 41 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 31 -1 33 -1 -1 0 1 -1 -1 -1 -1 -1 -1 41 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 28 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 26 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 17 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 36 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 39 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 79 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 54 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 23 -1 -1 -1 -1 -1 34 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 52 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 19 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 17 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1
1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0
map2.txt
30
0 12 -1 16 -1 -1 -1 -1 -1 -1 -1 100 -1 119 -1 -1 -1 -1 -1 -1 42 -1 -1 -1 -1 -1 51 -1 -1 -1
-1 0 1 -1 -1 -1 -1 -1 -1 -1 99 -1 201 -1 -1 -1 -1 -1 -1 -1 41 -1 -1 -1 -1 -1 -1 16 -1 119
51 -1 0 1 -1 9 -1 -1 25 -1 -1 76 -1 -1 -1 45 -1 -1 38 31 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 26 0 1 -1 26 -1 -1 -1 29 -1 -1 30 -1 87 -1 -1 -1 -1 -1 -1 -1 41 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
30 -1 17 -1 -1 0 1 -1 -1 42 -1 -1 42 -1 -1 41 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 31 -1 33 -1 -1 0 1 -1 -1 -1 -1 -1 -1 41 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 28 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 26 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 17 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 36 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 39 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 79 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 54 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 23 -1 -1 -1 -1 -1 34 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 52 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 19 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 17 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1 -1
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0 1
1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0