Mixed Messages philosophers' quotes

Hello everyone!

I would like to share my take on the portfolio project. I appreciate any comments and tips. The project is completed but I might go back to it later to make it a bit more complex.

I decided to go the easy way but you certainly can complicate this task and make it much more impressive. It took me approx 2hrs with getting my head around GitHub.

Here is the link:

Many Thanks
Mickey

Anything we can do with a switch, we can do with an object.

philosophers = [ plato, socrates, sunTzu, voltaire, deSade ]

If all the objects are left out on their own, the above is all their identifiers in iterable form.

This is all the keys if the objects are in an object,

philosophers = [ 'plato', 'socrates', 'sunTzu', 'voltaire', 'deSade' ]

The thing with this project is there is no look-up, only polling of a random object with what is essentially an index to the above lists.

What if we don’t name the objects; rather, make them anonymous objects in an array? Pick one at random and we have the name and all their quotes.

Or even more simply, make every quote an object with a q and a property and leave them all jumbled in an array. Then pick any one of them randomly. We would still have the author and the quote paired up. This would get the whole shebang sewn up in one simple array of simple objects, none of which would need identifiers.

It follows we also have the means to extract individual lists of authors and all their quotes, but as a report, not a stored data structure. Is this making any sense?

1 Like
Quotes
quotes = [ 
  { q: `In the midst of chaos, there is also opportunity`,
    a: `Sun Tzu` },
  { q: `The greatest victory is that which requires no battle.`,
    a: `Sun Tzu` },
  { q: `Even the finest sword plunged into salt water will eventually rust.`,
    a: `Sun Tzu` },
  { q: `When you surround an army, leave an outlet free. Do not press a desperate foe too hard.`,
    a: `Sun Tzu` },
  { q: `When the enemy is relaxed, make them toil. When full, starve them. When settled, make them move.`,
    a: `Sun Tzu` },
  { q: `So in war, the way is to avoid what is strong, and strike at what is weak.`,
    a: `Sun Tzu` },
  { q: `The man who alters his way of thinking to suit others is a fool.`,
    a: `Marquis De Sade` },
  { q: `Social order at the expense of liberty is hardly a bargain.`,
    a: `Marquis De Sade` },
  { q: `I don't know what the heart is, not I: I only use the word to denote the mind's frailties.`,
    a: `Marquis De Sade` },
  { q: `Religions are the cradles of despotism.`,
    a: `Marquis De Sade` },
  { q: `True happiness lies in the senses, and virtue gratifies none of them.`,
    a: `Marquis De Sade` },
  { q: `Happiness is an abstraction, it is a product of the imagination, it is a way of being moved, which depends entirely on our way of seeing and feeling.`,
    a: `Marquis De Sade` },
  { q: `Life is a shipwreck, but we must not forget to sing in the lifeboats.`,
    a: `Voltaire` },
  { q: `The more I read, the more I acquire, the more certain I am that I know nothing.`,
    a: `Voltaire` },
  { q: `Common sense is not so common.`, a: `Voltaire` },
  { q: `God is a comedian playing to an audience that is too afraid to laugh.`,
    a: `Voltaire` },
  { q: `The most important decision you make is to be in a good mood.`,
    a: `Voltaire` },
  { q: `Doubt is an uncomfortable condition, but certainty is a ridiculous one.`,
    a: `Voltaire` },
  { q: `Employ your time in improving yourself by other men’s writings so that you shall come easily by what others have labored hard for.`,
    a: `Socrates` },
  { q: `The beginning of wisdom is a definition of terms.`,
    a: `Socrates` },
  { q: `What a lot of things there are a man can do without.`,
    a: `Socrates` },
  { q: `I cannot teach anybody anything. I can only make them think.`,
    a: `Socrates` },
  { q: `Slanderers do not hurt me because they do not hit me.`,
    a: `Socrates` },
  { q: `He who is not contented with what he has, would not be contented with what he would like to have.`,
    a: `Socrates` },
  { q: `Only the dead have seen the end of war.`, a: `Plato` },
  { q: `The heaviest penalty for declining to rule is to be ruled by someone inferior to yourself.`,
    a: `Plato` },
  { q: `I am the wisest man alive, for I know one thing, and that is that I know nothing.`,
    a: `Plato` },
  { q: `Never discourage anyone...who continually makes progress, no matter how slow.`,
    a: `Plato` },
  { q: `Ignorance, the root and stem of every evil.`, a: `Plato` },
  { q: `Love is a serious mental disease.`, a: `Plato` }
]
print = console.log;
n = quotes.length;
p = quotes[Math.floor(Math.random() * n)]
print (p)
{ q: 'He who is not contented with what he has, would not be contented with what he would like to have.',
  a: 'Socrates' }

Now if we could do in JS what we can do in Python (easily, that is)…

>>> from random import randrange
>>> x = list(range(1, 10))
>>> n = len(x)
>>> q = x.pop(randrange(n))
>>> x.append(q)
>>> n -= 1
>>> q = x.pop(randrange(n))
>>> x.append(q)
>>> n -= 1
>>> q = x.pop(randrange(n))
>>> x.append(q)
>>> n -= 1
>>> q = x.pop(randrange(n))
>>> x.append(q)
>>> n -= 1
>>> q = x.pop(randrange(n))
>>> x.append(q)
>>> n -= 1
>>> q = x.pop(randrange(n))
>>> x.append(q)
>>> n -= 1
>>> q = x.pop(randrange(n))
>>> x.append(q)
>>> n -= 1
>>> q = x.pop(randrange(n))
>>> x.append(q)
>>> n -= 1
>>> q = x.pop(randrange(n))
>>> x.append(q)
>>> n -= 1
>>> q = x.pop(randrange(n))
Traceback (most recent call last):
  File "<pyshell#64>", line 1, in <module>
    q = x.pop(randrange(n))
  File "C:\Users\..\Python38\lib\random.py", line 216, in randrange
    raise ValueError("empty range for randrange()")
ValueError: empty range for randrange()
>>> x
[1, 3, 2, 9, 4, 5, 7, 8, 6]
>>> 

Now, if we could only do that in JS. We can, but not with that same ease. Mind, with some thinking we can make it easy. Any great minds out there?

1 Like

In JS we have to capture the element we wish to remove if it is not at the beginning or end of an array. That means a .slice() of the array gets assigned; the equivalent .splice() of the array gets executed. We .push() the slice to the array, and decrement n. Can anyone push out the code for this?

Hey!

Thank you for your reply! I see your point. You are right that could have been simplified just into arrays and a single object. Or as you mentioned just an array of simple objects picked at random! I will look into that to maybe make the random message mix different quotes into one random but in a way that it makes sense.

I haven’t started with Python yet. So I do not really understand the code in Python you have provided.

Now I have simplified the code, please can you let me know if that looks better?

In essence it is a step by step iteration of an ordered sequence, popping a random position, moving the value to the end, and pop another random position with a smaller upper bound, move it to the end, and so on until the range is empty. The result is a shuffled array.

Normally that would all happen in a loop. I’m currently working out how to do similar steps in JS.

It gets rid of the bulky switch. What do you think of the result?

1 Like

Wrote a shuffle function to increase randomness.

const randrange = function (n) {
  return Math.floor(Math.random() * n)
}
const shuffle = function (arr) {
  n = arr.length
  while (n > 0) {
    r = randrange(n)
    s = arr[r]
    arr.splice(r,1)
    arr.push(s)
    n -=1
  }
  //return arr
}
shuffle(quotes)
//print (quotes)
n = quotes.length;
p = quotes[randrange(n)]
//print (p)
print (`${p.q} ~ ${p.a}`)
Slanderers do not hurt me because they do not hit me. ~ Socrates
1 Like

Lastly, please post a link to the project page. Thank you.

Shuffle REPL

Oh that looks very clever! Thank you.

Where should I post the link? I am not sure what do you mean? As in add the reference to the project with your code?

1 Like

Just post the link in a reply. The page I’m referring to is the one that sets out the parameters for this project.

The use of splice and push aren’t needed. It’s more efficient to just swap the values of arr[n] and arr[r] in place. The most common ways are using a temporary variable or destructuring.

const shuffle = function (arr) {
  n = arr.length
  while (n > 0) {
    r = randrange(n)
    n--; // Make sure after random as it is exclusive of the upper value and before using to get index, otherwise it will be out of range.
    //const temp = arr[n];
    //arr[n] = arr[r];
    //arr[r] = temp;
    [arr[n], arr[r]] = [arr[r], arr[n]];
  }
}

For anyone that wants to read up on this more, this algorithm is the Knuth or Fisher-Yates shuffle.

2 Likes

Yeah, I had thought of using the swap but opted for a more naive approach. It’s simple and O(N) and a tad easier to follow for a learner.

It would be interesting to see how the two work on large arrays in terms of time.

sample = range(100000)
time = ""
console.time("time")
shuffle(sample)
console.timeEnd("time")
// splice/push     => 100000    =>  time: 25235.407ms
// swap            => 100000    =>  time: 1075.280ms
// swap            => 1000000   =>  time: 8794.328ms

Case closed!

Fisher-Yates shuffle

Time to back out of the notion of O(N) now that I’ve realized Array.splice() is an iterator, of sort. That means, O(N**2) and probably squared again. It’s all moot, now, though. We know never to do that again. How good it is to put that one behind us.