Updated: I realize that in C I initialized the word counter 1. (I've tried to delete the inquiry but I was not allowed) :/
in order to try to learn to code I signed up for CS50 and on PSET2 there's an exercise called "Readability". I'm trying to recreate the program with JavaScript. According to the instructions provided the output of input should be 55 words but I'm getting 54.
My For Loop is iterating over each element of the array and if it finds a space, it will add 1 to the words counter (my guess is that it is not counting the last word because it ends with a ".")
However, my C program code seems to work fine.
JavaScript Code:
let text = "It was a bright cold day in April, and the clocks were striking thirteen. Winston Smith, his chin nuzzled into his breast in an effort to escape the vile wind, slipped quickly through the glass doors of Victory Mansions, though not quickly enough to prevent a swirl of gritty dust from entering along with him."
let words = 0;
let textArray = Array.from(text);
//Words
for (let i = 0; i < textArray.length; i++){
if (textArray[i] == " "){
words ++;
}
}
console.log("Words: " + words);
C Program Code
#include <cs50.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
int main(void)
{
//Ask user for text
string text = get_string("Text: ");
//define variables
int letters = 0;
int words = 1;
int sentences = 0;
//loop to analyze text
for (int i = 0; i < strlen(text); i++)
{
//count letters
if ((text[i] >= 'a' && text[i] <= 'z') || (text[i] >= 'A' && text[i] <= 'Z'))
{
letters++;
}
//count words
else if (text[i] == ' ')
{
words++;
}
//count sentences
else if ((text[i] == '.') || (text[i] == '?') || (text[i] == '!'))
{
sentences++;
}
}
printf("Words: %i\n", words);
//math calculation (third rule)
float l = 100 * ((float) letters / (float) words);
float s = 100 * ((float) sentences / (float) words);
//printf("l: %i\n", (int) round(l));
//printf("s: %i\n", (int) round(s));
//grade index formula
float grade = (0.0588 * l) - (0.296 * s) - 15.8;
if (grade >= 16)
{
printf("Grade 16+\n");
}
else if (grade < 1)
{
printf("Before Grade 1\n");
}
else
{
printf("Grade %i\n", (int) round(grade));
}
}
If there are 4 spaces in a well-formed sentence then there are 5 words. Example:
"I am a boy" - 3 spaces, 4 words
The above is a naive generalization but for simple cases this is true.
So you can maybe initialize words from 1 instead of 0. This is a very naive solution, but will help as a starting step.
let text = "It was a bright cold day in April, and the clocks were striking thirteen. Winston Smith, his chin nuzzled into his breast in an effort to escape the vile wind, slipped quickly through the glass doors of Victory Mansions, though not quickly enough to prevent a swirl of gritty dust from entering along with him."
let words = 1;
let textArray = Array.from(text);
//Words
for (let i = 0; i < textArray.length; i++){
if (textArray[i] == " "){
words ++;
}
}
console.log("Words: " + words);
EDIT
: Your C code initializes words with 1 so that is the offset.
If there is a single space in two text then word should be number of space + 1
e.g hello world so there is only 1 space so number of word will be 2
let text =
"It was a bright cold day in April, and the clocks were striking thirteen. Winston Smith, his chin nuzzled into his breast in an effort to escape the vile wind, slipped quickly through the glass doors of Victory Mansions, though not quickly enough to prevent a swirl of gritty dust from entering along with him.";
const words = Array.from(text).filter((s) => s === " ").length + 1;
console.log("Words: " + words);
You can use regex here /\s+/
let text =
"It was a bright cold day in April, and the clocks were striking thirteen. Winston Smith, his chin nuzzled into his breast in an effort to escape the vile wind, slipped quickly through the glass doors of Victory Mansions, though not quickly enough to prevent a swirl of gritty dust from entering along with him.";
const words = text.split(/\s+/g).length;
console.log("Words: " + words);
What is wrong with this answer? Isn't this simple
let text = "It was a bright cold day in April, and the clocks were striking thirteen. Winston Smith, his chin nuzzled into his breast in an effort to escape the vile wind, slipped quickly through the glass doors of Victory Mansions, though not quickly enough to prevent a swirl of gritty dust from entering along with him."
let words = 0;
// removing special characters and convert to array by space
let wordCount = text.replace(/[^\w\s]/gi, '').split(" ").length;
console.log(wordCount) // 55
The answers are correct, but the point is the initialize.
If the text is empty, the 'words' should be 0.
let text = "It was a bright cold day in April, and the clocks were striking thirteen. Winston Smith, his chin nuzzled into his breast in an effort to escape the vile wind, slipped quickly through the glass doors of Victory Mansions, though not quickly enough to prevent a swirl of gritty dust from entering along with him."
const textArray = Array.from(text);
let words = (textArray.length)? 1 : 0; // set initial value for words.
textArray.forEach(e => {
if (e === " ") words++;
});
console.log("Words: " + words);
And you can use this line to change string to array.
// const textArray = Array.from(text);
const textArray = [ ...text ];
Related
Consider all the strings of length 6 composed of capital Latin letters (A - Z), sorted in lexicographic order. The string AAAAAA is the first. The string AAAAAZ is the 26th . The 27th is AAAABA. The hint to this problem is the Nth string where N is the number of primes less than 2^ 30 − M . M is a permutation of 123456789, and we won’t tell you which one it is, but we will give you the following constraints to reduce the space of possibilities:
M is divisible by 567.
M starts with 2, ends with 4, and the middle digit is 8.
I managed to find M and the Nth, but I am not able to find a solution on how to find the right string based on the ranking. Please note that I found 9 possibilities on the ranking (Nth) which are:
43973488
43929860
41992802
41914646
41831591
41232030
41066565
40861259
40167328
Thank you for your help.
you need to convert the numbers to base 26 , and match each digit to the related chars
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
function convertToBase26Strings(number) {
number = number - 1 ;
var res = ""
while(number >= chars.length ) {
var i = number % chars.length ;
number = Math.floor(number / chars.length)
res += chars[i];
}
res += chars[number];
return res.split("").reverse().join("").padStart(6 , "A");
}
console.log(convertToBase26Strings(1));
console.log(convertToBase26Strings(26));
console.log(convertToBase26Strings(27));
Lets say we have a chess fen and the fen is a black to play and win problem. Many times chess puzzle websites want to avoid the confusion of having to keep indicating who's turn it is to move so they rather just put all the puzzles as white to play and win or black to play and win. In a case or scenario where I have a array or db of 1000 fens where its black to play and win is there a way I can run it through a function or algo that will spit out the fen for the exact same position except white to play and win?
I've tried setting editing the board to have all the black pieces be white pieces and white pieces be black pieces but ran into the issue that the board was upside down and pawns move in only one direction.
starting fen for black to play and win.
7k/8/7K/8/ppp5/8/PPP5/8 b - - 0 1
Fen I want to arrive at from running:
function flipfen(fen) {
return (fen*(algorithm))
};
˚console.log(flipfen(7k/8/7K/8/ppp5/8/PPP5/8 b - - 0 1))
And the desired result:
8/5ppp/8/5PPP/8/k7/8/K7 w - - 0 1
Maybe I can use regular expressions? it looks like the second fen (in this case not sure if it will work in all cases is just the other one backwards with some slight changes? ) `
8/5ppp/8/5PPP/8/k7/8/K7 w - - 0 1
I tried to think of every possible valid FEN.
invert the letters case
reverse the rows order
switch who's to move
swap castling rights
mirror the en passant square
function flipFEN(FEN) {
const invertCase = (char) => {
if (char == char.toLowerCase())
return char.toUpperCase();
return char.toLowerCase();
}
let position = FEN.split(" ")[0].split("/");
position = position.map((row) => {
return row.split("").map(invertCase).join("");
});
position = position.reverse().join("/");
let turn = FEN.split(" ")[1];
turn = turn == "w" ? "b" : "w";
let castle = FEN.split(" ")[2];
if (castle != "-") {
castle = castle.split("").map(invertCase);
castle.sort();
castle = castle.join("");
}
let ep = FEN.split(" ")[3];
if (ep != "-") {
ep = ep.split("");
ep[1] = ep[1] == "6" ? "3" : "6";
ep = ep.join("");
}
const rest = FEN.split(" ").slice(4);
return [position, turn, castle, ep, ...rest].join(" ");
}
console.log(flipFEN("r1bq1r2/pp2n3/4N2k/3pPppP/1b1n2Q1/2N5/PP3PP1/R1B1K2R w KQ g6 0 15"));
// > "r1b1k2r/pp3pp1/2n5/1B1N2q1/3PpPPp/4n2K/PP2N3/R1BQ1R2 b kq g3 0 15"
I make my own dictionary, I keep all word in an object. I use by put some content into content variable
and loop for find the word if which word found, should add message.
How I have to do it?
Can I have result like this
Boom is an American company. It wants to make a new plane. The plan is to have a plane in 2023 The plane will(to happen in the future) be supersonic. It will(to happen in the future) fly from London to New York in three hours. The flight(a journey in an aircraft) ticket will(to happen in the future) not be extremely expensive. It will(to happen in the future) cost as much as a standard business class ticket.
mycode
let content = "Boom is an American company. It wants to make a new plane. The plan is to have a plane in 2023 The plane will be supersonic. It will fly from London to New York in three hours. The flight ticket will not be extremely expensive. It will cost as much as a standard business class ticket.";
var myDictionary =
{
will: "to happen in the future",
flight: "a journey in an aircraft",
cost: "the amount of money needed to buy",
particular: "or this and not any other"
}
for(let i in myDictionary) {//each word
for(i=0;/**/)//this word found, such as "will" have to 4 rounds
{
/*loop for find, how many position in this word.
if this word has 2 positions that first loop add my transalate message after the fist position of word and round 2, if more it's have to keep loop until no found this position and out to main loop for find next word
add in the second position.
*/
generate(i);
}
}
function generate(word)
{
let find_position = content.indexOf(word);
console.log(find_position);
let length_of_word = word.length;
let find_position_after_word = find_position + length_of_word;
let transalate_word = getProperty(word);
let output = content.slice(0, find_position_after_word), transalate_word, content.slice(find_position_after_word)].join('');
}
function getProperty(word_for_transalate)
{
return myDictionary[word_for_transalate];
}
Try reduce with replace
var output = Object.keys(myDictionary).reduce( function(a,b,i){
if (i == 1)
{
a = content.replace( new RegExp( a, "gi" ), a + "(" + myDictionary[ a ] + ")" );
}
a = a.replace( new RegExp( b, "gi" ), b + "(" + myDictionary[ b ] + ")" );
return a;
});
Demo
var content = "Boom is an American company. It wants to make a new plane. The plan is to have a plane in 2023 The plane will be supersonic. It will fly from London to New York in three hours. The flight ticket will not be extremely expensive. It will cost as much as a standard business class ticket.";
var myDictionary = {
will: "to happen in the future",
flight: "a journey in an aircraft",
cost: "the amount of money needed to buy",
particular: "or this and not any other"
};
var output = Object.keys(myDictionary).reduce(function(a, b, i) {
if (i == 1) {
a = content.replace(new RegExp(a, "gi"), a + "(" + myDictionary[a] + ")");
}
a = a.replace(new RegExp(b, "gi"), b + "(" + myDictionary[b] + ")");
return a;
});
console.log( output );
Find position of string within your string and append the value of key-value pair next to it within braces.
var a = "Boom is an American company. It wants to make a new plane.";
var obj = {
"wants" : "2",
"is": "one"
}
for(var key in obj) {
let position = a.indexOf(key) + key.length + 1;
a = [a.slice(0, position), '('+obj[key]+')', a.slice(position)].join('');
}
console.log(a)
For the sake of explaining, imagine I have 101 entities. The entities are all people.
In the first entity, it has x amount of "potatoes", I want it to have y potatoes, for now I shall use 950 as an example, intentionally choosing a more awkward number than 1000 for testing.
var personOne = {
...
potatoes: 100
}
I have 100 more of these entities which may have any number of potatoes, but I set a constant buffer that at least 100 for the sake of example again - have to remain with each person.
This means for all of the entities that have over 100, I will be taking some from them - I want this to be shared proportionally across all of them, so that 850 aren't taken from the first two or three, but 10 or 5 taken from all those that are capable of providing such an amount.
Any ideas for an approach?
Optionally: I am using more properties than one "potatoes" property, but I plan on looping through each type and re-using the method that I find to each. I am unsure as to whether this could affect the answer.
Important / Simplified
The one entitiy is pulling "potatoes" from all of the other entities, they are not being distributed evenly across all of them - they are being taken to one entity. I just do not want to do it in a way that is not proportional across all other 100 entities.
This is more taxation than cake-cutting. I am struggling to google for or think of the correct name for the mathematical problem.
Case 1. enough potatoes for everyone to have over 100 of them: put all potatoes together and divide evenly.
Case 2. Not enough potatoes for everyone to have 100. Sum the excess over 100 for those who have + sum all potatoes of those with less than 100, divide the collected potatoes between those with under 100.
(yes, case 2 will imply that some of those under 100 will end with less potatoes than they started. Not fair? Well, maybe you shouldn't protect the 1-percenters that much if there aren't enough potatoes for everybody :) But I digress)
I hope this time i understood the problem. I would calculate the percentage of excess potatoes needed to get the desired amount of potatoes and take that percentage of each participant's excess potatoes, or all if there are not enough total.
Here is some demonstration code to clarify. It is probably overly verbose but should only serve to show the intention anyways. I assumed a very precise potato-cutter is available, as there was no rule specified about what to do about rounding. The outputs are the potatoes of the participants before and after the redistribution. I set NUMBER_OF_PARTICIPANTS to 4 so the output is somewhat readable.
const MAXIMUM_START_POTATOES = 1234;
const MINIMUM_KEPT_POTATOES = 100;
const ENTITY_TAKING_POTATOES = 0;
const DESIRED_POTATOES = 950;
const NUMBER_OF_PARTICIPANTS = 4;
//generate NUMBER_OF_PARTICIPANTS entities with random amount of potatoes
let entities = [];
for (let i = 0; i < NUMBER_OF_PARTICIPANTS; i++) {
entities.push(Math.floor(Math.random() * (MAXIMUM_START_POTATOES + 1)));
}
console.log(entities);
let required_potatoes = DESIRED_POTATOES - entities[ENTITY_TAKING_POTATOES];
if (required_potatoes <= 0) console.log("nothing to do.");
else {
let excess_potatoes = 0;
//Sum excess available potatoes
for (let i = 0; i < NUMBER_OF_PARTICIPANTS; i++) {
if (i === ENTITY_TAKING_POTATOES) continue;
excess_potatoes += Math.max(0, entities[i] - MINIMUM_KEPT_POTATOES);
}
if (excess_potatoes < required_potatoes) {
//just take all excess potatoes
for (let i = 0; i < NUMBER_OF_PARTICIPANTS; i++) {
if (i === ENTITY_TAKING_POTATOES) continue;
entities[i] = Math.min(entities[i], MINIMUM_KEPT_POTATOES);
}
entities[ENTITY_TAKING_POTATOES] += excess_potatoes;
} else {
//calculate percentage of the excess potatoes that is needed
let percentage_required = required_potatoes / excess_potatoes;
//Take that percentage off every participant's excess potatoes
for (let i = 0; i < NUMBER_OF_PARTICIPANTS; i++) {
if (i === ENTITY_TAKING_POTATOES) continue;
entities[i] -= Math.max(0, entities[i] - MINIMUM_KEPT_POTATOES) * percentage_required;
}
//Assume double precision is enough for this to never be an issue
entities[ENTITY_TAKING_POTATOES] = DESIRED_POTATOES;
}
console.log(entities);
}
I have this complex question from my customer, I can't find a answer on it so now I will try to ask you guys.
The quest is the following:
I think that one rule might be: Dots
which appears immediately after a
number, not counted as sentences. This
means that sentence present in the
"8. marts"and "2.567" is not counted as
word dots. In return, each word dots
may be overlooked (if now a sentence
ends with a number: "Vi kommer kl. 8")
but it's probably after all not quite
as often.
Another might be: If there is one
character (a letter or number)
immediately after a sentence is not a
phrase sentence. That would make that
we avoided counting the sentence
present in the "f.eks.", "bl.a."
and "cand.mag.".
I hope I can be helped here.
My code:
<script>
function word_count(field, count) {
var wordsNumberOverSeven = 0;
var wordsNumber = 0
var contentText = $(\'#lix_word_count\').val();
contentText = contentText.replace(\'?\', \'.\');
contentText = contentText.replace(\'!\', \'.\');
contentText = contentText.replace(\',\', \'\');
contentText = contentText.replace(\';\', \'\');
contentText = contentText.replace(\':\', \'\');
contentText = contentText.replace(\'\n\', \' \').replace(/^\s+|\s+$/g,\'\').replace(/\s\s+/g,\' \');
var matchDots = contentText.split(\'.\').length-1;
var match = contentText.split(\' \');
$.each(match, function(){
if ( this.length > 0 )
wordsNumber += 1;
if ( this.length >= 7 )
{
wordsNumberOverSeven += 1;
}
});
var lixMatWords = wordsNumber / matchDots;
var lixMatLongWords = ( wordsNumberOverSeven * 100 ) / wordsNumber;
var lixMatch = Math.round(( lixMatWords + lixMatLongWords ) *100)/100;
var lixType = \'\';
if ( lixMatch <= 24 )
lixType = \'Lixen i din tekst er \'+ lixMatch +\', dvs. at teksten er meget let at læse.\';
else if ( lixMatch <= 34 )
lixType = \'Lixen i din tekst er \'+ lixMatch +\', dvs. at teksten er let at læse\';
else if ( lixMatch <= 44 )
lixType = \'Lixen i din tekst er \'+ lixMatch +\', dvs. at teksten ligger i midterområdet.\';
else if ( lixMatch <= 54 )
lixType = \'Lixen i din tekst er \'+ lixMatch +\', dvs. at teksten er svær at læse.\';
else
lixType = \'Lixen i din tekst er \'+ lixMatch +\', dvs. at teksten er meget svær at læse.\';
/** alert(lixType +\'\nDots: \'+ matchDots +\'\nWords: \'+ wordsNumber +\'\nLangeord: \'+ wordsNumberOverSeven); **/
alert(lixType);
}
</script>
I think we need to see the rest of the rules, or a few more at least.
Perhaps it would be better to describe what you want to include as a sentence, rather than what to exclude. If you are looking for full sentences, then it might be a period preceded by a non-whitespace character and followed by a space or new line or line feed, or some more complex rule set. It may require more than one regular expression with some other logic to sort the more complex cases.
If you want to split sentences based on that rule, then something like
mySentences.match(/(?:[^.0-9]|[0-9]+\.?|\.[a-z0-9])+(?:\.|$)/ig)
should do it.
You'll have to expand a-z to include accented characters in your language, but that should do it.
It produces the following for your input text.
["I think that one rule might be: Dots which appears immediately after a number, not counted as sentences.",
" This means that sentence present in the \"8. marts\"and \"2.567\" is not counted as word dots.",
" In return, each word dots may be overlooked (if now a sentence ends with a number: \"Vi kommer kl.",
" 8\") but it's probably after all not quite as often.",
"\n\nAnother might be: If there is one character (a letter or number) immediately after a sentence is not a phrase sentence.",
" That would make that we avoided counting the sentence present in the \"f.eks.",
"\", \"bl.a.","\" and \"cand.mag.",
"\"."]
so obviously it has trouble with dots that appear inside quoted sections. You could fix that up by walking and rejoining as long as a sentence ends inside a quoted section.
// Given mySentences defined above, walk counting quote characters.
// You could modify the regexp below if your language tends to use
// a different quoting style, e.g. French-style angle quotes.
for (var i = 0; i < mySentences.length - 1; ++i) {
var quotes = mySentences[i].match(/["\u201c\u201d]/g);
// If there are an odd number of quotes, combine the next sentence
// into this one.
if (quotes && quotes.length % 2) {
// In English, it is common to end the quoted section after the
// closing punctuator: Say "hello."
var next = mySentences[i + 1];
if (/^["\u201c\u201d]/.test(next)) {
mySentences[i] += next.substring(0, 1);
mySentences[i + 1] = next.substring(1);
} else {
mySentences[i] += next;
mySentences.splice(i, 1);
--i; // See if there's more to combine into this sentence.
}
}
}
This kind of stuff is pretty brittle though. If you want to know how it's done by people who specialize in this kind of thing, search for "natural language segmentation."